home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / mus / play / multiplsr.lha / medplay.asm < prev    next >
Assembly Source File  |  1992-09-14  |  85KB  |  3,114 lines

  1. * MultiPlayer
  2. * Copyright (C) 1992 Bryan Ford
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. *
  18. * See Player.doc for info on contacting the author of this program.
  19. *
  20. * Note:  This playroutine was not originally written by me.  In general
  21. * these playroutines are public domain, so I am bringing the versions
  22. * modified for MultiPlayer under the General Public License.  In the
  23. * few cases of already-copyrighted playroutines, the above copyright
  24. * notice applies only to the parts of the file written by me.
  25. *
  26. * $Id: medplay.asm,v 4.2 92/07/19 16:36:30 BAF Exp $
  27. *
  28.  
  29.         include "exec/types.i"
  30.         include "bry/macros.i"
  31.         include "player.i"
  32.  
  33.         xref    modmem,dieerrplay,intsongpos,intrepeat,parseauthor,prepstring
  34.         xref    intflashnote,intflashsample,addinfo
  35.  
  36.         xdef    medstart
  37.  
  38.         ; OctaMED Pro 8-channel player
  39.         xref    _InitPlayer8,_RemPlayer8,_PlayModule8,_StopPlayer8,_ContModule8,_modnum8
  40.  
  41.         code    text
  42.  
  43. *** Entrypoint from MultiPlayer
  44.  
  45. medstart:
  46.         clr.l   authorname(a4)
  47.  
  48.         move.l  modmem(a4),a0           ; Check for 8 channel modules
  49.         add.l   mmd_songinfo(a0),a0
  50.         btst    #6,msng_flags(a0)
  51.         sne.b   is8(a4)
  52.  
  53.         plstartret .gmod
  54.  
  55. .init
  56.         move.l  modmem(a4),-(sp)        ; Relocate the module
  57.         bsr     _RelocModule
  58.         addq    #4,sp
  59.         bsr     parseinfo
  60.         moveq   #0,d0
  61.         rts
  62.  
  63. .start
  64.         move.w  d0,_modnum
  65.         move.w  d0,_modnum8
  66.         tst.b   is8(a4)                 ; Initialize the player
  67.         bnz.b   .start_8
  68. .start_4
  69.         bsr     _InitPlayer
  70.         tst.l   d0
  71.         bne     dieerrplay
  72.         move.l  modmem(a4),a0
  73.         bra     _PlayModule
  74. .start_8
  75.         bsr     _InitPlayer8
  76.         tst.l   d0
  77.         bne     dieerrplay
  78.         move.l  modmem(a4),a0
  79.         bra     _PlayModule8
  80.  
  81. .cont
  82.         tst.b   is8(a4)                 ; Continue playing
  83.         bnz.b   .cont_8
  84. .cont_4
  85.         bsr     _InitPlayer
  86.         tst.l   d0
  87.         bne     dieerrplay
  88.         move.l  modmem(a4),a0
  89.         bsr     _ContModule
  90.         moveq   #1,d0
  91.         rts
  92. .cont_8
  93.         bsr     _InitPlayer8
  94.         tst.l   d0
  95.         bne     dieerrplay
  96.         move.l  modmem(a4),a0
  97.         bsr     _ContModule8
  98.         moveq   #1,d0
  99.         rts
  100.  
  101. .stop
  102.         move.l  modmem(a4),a0
  103.         tst.b   is8(a4)
  104.         bnz.b   .stop_8
  105. .stop_4
  106.         bsr     _StopPlayer
  107.         bra     _RemPlayer
  108. .stop_8
  109.         bsr     _StopPlayer8
  110.         bra     _RemPlayer8
  111.  
  112. .makername
  113.         lea     name(a4),a0             ; GetMakerName
  114.         move.l  a0,d0
  115.         rts
  116.  
  117. .numsongs
  118.         move.l  modmem(a4),a0
  119.         moveq   #0,d0
  120.         move.b  mmd_songsleft(a0),d0
  121.         addq.w  #1,d0
  122.         rts
  123.  
  124.         cnop    0,4
  125.         dc.l    gmod_Jump
  126. .gmod   gmodbra .init                   ; InitMusic
  127.         gmodbra .start                  ; StartMusic
  128.         gmodbra .stop                   ; StopMusic
  129.         gmodnop                         ; EndMusic
  130.         gmodnop
  131.         gmodbra .cont                   ; Continue
  132.         gmodnop
  133.         gmodnop
  134.         gmodnop
  135.         gmodnop
  136.         gmodnop
  137.         gmodnop
  138.         gmodbra .numsongs               ; GetNumSongs
  139.         gmodbra med_getsongname         ; GetSongName
  140.         gmodbra med_getauthorname       ; GetAuthorName
  141.         gmodnop
  142.         gmodnop
  143.         gmodbra .makername              ; GetMakerName
  144. ;        move.l  #GMODHF_SEQUENCE!GMODHF_REPEAT,d0       ; Hook
  145.         rts
  146.  
  147.  
  148. parseinfo
  149.         apush4
  150.  
  151.         move.l  modmem(a4),a0
  152.         tst.w   d0
  153.         beq.s   \notfnd
  154. \nxtmod tst.l   mmd_expdata(a0)
  155.         beq.s   \notfnd
  156.         move.l  mmd_expdata(a0),a1
  157.         tst.l   (a1)
  158.         beq.s   \notfnd
  159.         move.l  (a1),a0
  160.         subq.w  #1,d1
  161.         bgt.s   \nxtmod
  162. \notfnd
  163.         move.l  8*4(a0),d0              ; Find the annotext
  164.         beq.s   9$
  165.         move.l  d0,a0
  166.         move.l  3*4(a0),d2
  167.         beq.s   9$
  168.         move.l  d2,a2
  169.  
  170.         move.l  a2,a0                   ; Put this in the module info display
  171.         bsr     addinfo
  172.  
  173.         move.l  a2,a0                   ; Find the author name
  174.         jsr     parseauthor
  175.         move.l  a0,d0
  176.         beq.s   5$
  177.         clr.b   (a1)                    ; Chop off the author name
  178.         bsr     prepstring
  179.         move.l  a0,d0
  180.         bz.b    5$
  181.         move.l  a0,authorname
  182. 5$
  183.         move.l  a2,a0                   ; Find the song name
  184.         bsr     prepstring
  185.         move.l  a0,songname
  186.  
  187. 9$      apop4
  188.         rts
  189.  
  190.  
  191. med_getsongname
  192.         move.l  songname,d0
  193.         rts
  194.  
  195.  
  196. med_getauthorname
  197.         move.l  authorname,d0
  198.         rts
  199.  
  200.  
  201. *** Relocation routine
  202. reloci    move.l    24(a2),d0
  203.     beq.s    xloci
  204.     movea.l    d0,a0
  205.     moveq   #0,d0
  206.     move.b  787(a1),d0    ;number of samples
  207.     subq.b  #1,d0
  208. relocs:    bsr.s   relocentr
  209.     move.l    -4(a0),d3    ;sample ptr
  210.     beq.s    nosyn
  211.     move.l    d3,a3
  212.     tst.w    4(a3)
  213.     bpl.s    nosyn        ;type >= 0
  214.     move.w    20(a3),d2    ;number of waveforms
  215.     lea    278(a3),a3    ;ptr to wf ptrs
  216.     subq.w    #1,d2
  217. relsyn:    add.l    d3,(a3)+
  218.     dbf    d2,relsyn
  219. nosyn:    dbf     d0,relocs
  220. xloci    rts
  221. norel    addq.l    #4,a0
  222.     rts
  223. relocentr:
  224.     tst.l   (a0)
  225.     beq.s   norel
  226.     add.l   d1,(a0)+
  227.     rts
  228. _RelocModule:
  229.     move.l    4(sp),a0    ;get module pointer from stack
  230.     movem.l    a2-a3/d2-d3,-(sp)
  231.     movea.l a0,a2
  232.     move.l  a2,d1        ;d1 = ptr to start of module
  233.     bsr.s    relocp
  234.     movea.l 8(a2),a1
  235.     bsr.s    reloci
  236. rel_lp    bsr.s    relocb
  237.     move.l    32(a2),d0    ;extension struct
  238.     beq.s    rel_ex
  239.     move.l    d0,a0
  240.     bsr.s    relocentr    ;ptr to next module
  241.     bsr.s    relocentr    ;InstrExt...
  242.     addq.l    #4,a0        ;skip sizes of InstrExt
  243. ; We reloc the pointers of MMD0exp, so anybody who needs them can easily
  244. ; read them.
  245.     bsr.s    relocentr    ;annotxt
  246.     addq.l    #4,a0        ;annolen
  247.     bsr.s    relocentr    ;InstrInfo
  248.     addq.l    #8,a0
  249.     bsr.s    relocentr    ;rgbtable (not useful for most people)
  250.     addq.l    #4,a0        ;skip channelsplit
  251.     bsr.s    relocentr    ;NotationInfo
  252.     bsr.s    relocentr    ;songname
  253.     addq.l    #4,a0        ;skip song name length
  254.     bsr.s    relocentr    ;MIDI dumps
  255.     bsr.s    relocmdd
  256.     move.l    d0,a0
  257.     move.l    (a0),d0
  258.     beq.s    rel_ex
  259.     move.l    d0,a2
  260.     bsr.s    relocp
  261.     movea.l 8(a2),a1
  262.     bra.s    rel_lp
  263. rel_ex    movem.l    (sp)+,d2-d3/a2-a3
  264.     rts
  265.  
  266. relocp    lea    8(a2),a0
  267.     bsr.s    relocentr
  268.     addq.l    #4,a0
  269.     bsr.s    relocentr
  270.     addq.l    #4,a0
  271.     bsr.s    relocentr
  272.     addq.l    #4,a0
  273.     bra.s    relocentr
  274.  
  275. relocb    move.l    16(a2),d0
  276.     beq.s    xlocb
  277.     movea.l    d0,a0
  278.     move.w  504(a1),d0
  279.     subq.b  #1,d0
  280. rebl    bsr.s   relocentr
  281.     dbf     d0,rebl
  282.     cmp.b    #'1',3(a2)    ;test MMD type
  283.     beq.s    relocbi
  284. xlocb    rts
  285.  
  286. relocmdd
  287.     tst.l    -(a0)
  288.     beq.s    xlocmdd
  289.     movea.l    (a0),a0
  290.     move.w    (a0),d0        ;# of msg dumps
  291.     addq.l    #8,a0
  292. mddloop    beq.s    xlocmdd
  293.     bsr    relocentr
  294.     bsr.s    relocdmp
  295.     subq.w    #1,d0
  296.     bra.s    mddloop
  297. xlocmdd    rts
  298.  
  299. relocdmp
  300.     move.l    -4(a0),d3
  301.     beq.s    xlocdmp
  302.     exg.l    a0,d3        ;save
  303.     addq.l    #4,a0
  304.     bsr    relocentr    ;reloc data pointer
  305.     move.l    d3,a0        ;restore
  306. xlocdmp    rts
  307.  
  308. relocbi    move.w    504(a1),d0
  309.     move.l    a0,a3
  310. biloop    subq.w    #1,d0
  311.     bmi.s    xlocdmp
  312.     move.l    -(a3),a0
  313.     addq.l    #4,a0
  314.     bsr    relocentr    ;BlockInfo ptr
  315.     tst.l    -(a0)
  316.     beq.s    biloop
  317.     move.l    (a0),a0
  318.     bsr    relocentr    ;hldata
  319.     bsr    relocentr    ;block name
  320.     bra.s    biloop
  321.  
  322.  
  323. ;    proplayer.a
  324. ;    ~~~~~~~~~~~
  325. ; The music player routine for MMD0 and MMD1 MED/OctaMED/OctaMED Professional
  326. ; four-channel modules.
  327.  
  328. ; Written by Teijo Kinnunen.
  329. ; If you find bugs in this routine, please notify:
  330. ;    Teijo Kinnunen
  331. ;    Oksantie 19
  332. ;    SF-86300  OULAINEN
  333. ;    FINLAND
  334. ;
  335. ; THIS CODE MAY BE FREELY USED AND DISTRIBUTED!
  336.  
  337. ;============================================================================
  338.  
  339. MIDI        EQU 0    ;1 = include MIDI code
  340. AUDDEV        EQU 0    ;1 = allocate channels using audio.device
  341. SYNTH        EQU 1    ;1 = include synth-sound handler
  342. CHECK        EQU 1    ;1 = do range checkings (track, sample in mem etc.)
  343. RELVOL        EQU 1    ;1 = include relative volume handling code
  344. IFFMOCT        EQU 1    ;1 = play IFF multi-octave samples correctly
  345. HOLD        EQU 1    ;1 = handle hold/decay
  346. PLAYMMD0    EQU 1    ;1 = play old MMD0 modules
  347. ;****** Timing control ******
  348. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  349. uCIAB    EQU    1    ;1 = use CIAB timers (default)
  350. ; Please use CIAB whenever possible to avoid problems with variable
  351. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  352. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  353. ; then you just call _IntHandler for each timing pulse.
  354.  
  355. ;============================================================================
  356.  
  357. ;If you are making a demo/game with only a single tune you'd like to
  358. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  359. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  360. ;You have to type the module name into the INCBIN statement (located near the
  361. ;end of this file, on line 2052).
  362.  
  363. EASY    EQU    0
  364.  
  365. ;Call _startmusic to play the music, and _endmusic to stop it (before
  366. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  367. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  368. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  369.  
  370. ;============================================================================
  371.  
  372. ;the MMD0 structure offsets
  373. mmd_id        EQU    0
  374. mmd_modlen    EQU    4
  375. mmd_songinfo    EQU    8
  376. mmd_blockarr    EQU    16
  377. mmd_smplarr    EQU    24
  378. mmd_expdata    EQU    32
  379. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  380. mmd_pblock    EQU    42
  381. mmd_pline    EQU    44
  382. mmd_pseqnum    EQU    46
  383. mmd_actplayline    EQU    48
  384. mmd_counter    EQU    50
  385. mmd_songsleft    EQU    51
  386.  
  387. ;the MMD0song structure
  388. ;Instrument data here (504 bytes = 63 * 8)
  389. msng_numblocks    EQU    504
  390. msng_songlen    EQU    506
  391. msng_playseq    EQU    508
  392. msng_deftempo    EQU    764
  393. msng_playtransp    EQU    766
  394. msng_flags    EQU    767
  395. msng_flags2    EQU    768
  396. msng_tempo2    EQU    769
  397. msng_trkvol    EQU    770
  398. msng_mastervol    EQU    786
  399. msng_numsamples    EQU    787
  400.  
  401. ;Instrument data
  402. inst_repeat    EQU    0
  403. inst_replen    EQU    2
  404. inst_midich    EQU    4
  405. inst_midipreset    EQU    5
  406. inst_svol    EQU    6
  407. inst_strans    EQU    7
  408.  
  409. ;Audio hardware offsets
  410. ac_ptr    EQU    $00
  411. ac_len    EQU    $04
  412. ac_per    EQU    $06
  413. ac_vol    EQU    $08
  414.  
  415. ;Trackdata sizes
  416. T03SZ    EQU    98
  417. T415SZ    EQU    20
  418.  
  419.         SECTION    "text",CODE
  420.  
  421.     IFNE    EASY
  422.  
  423.         XDEF    _startmusic,_endmusic
  424.  
  425. _startmusic    lea    easymod,a2
  426.         bsr.s    _RelocModule
  427.         bsr.w    _InitPlayer
  428.         lea    easymod,a0
  429.         bra.w    _PlayModule
  430.  
  431. _endmusic    bra.w    _RemPlayer
  432. ; ***** The relocation routine *****
  433. reloci        move.l    24(a2),d0
  434.         beq.s    xloci
  435.         movea.l    d0,a0
  436.         moveq   #0,d0
  437.         move.b  787(a1),d0    ;number of samples
  438.         subq.b  #1,d0
  439. relocs:        bsr.s   relocentr
  440.         move.l    -4(a0),d3    ;sample ptr
  441.         beq.s    nosyn
  442.         move.l    d3,a3
  443.         tst.w    4(a3)
  444.         bpl.s    nosyn        ;type >= 0
  445.         move.w    20(a3),d2    ;number of waveforms
  446.         lea    278(a3),a3    ;ptr to wf ptrs
  447.         subq.w    #1,d2
  448. relsyn        add.l    d3,(a3)+
  449.         dbf    d2,relsyn
  450. nosyn        dbf     d0,relocs
  451. xloci        rts
  452. norel        addq.l    #4,a0
  453.         rts
  454. relocentr    tst.l   (a0)
  455.         beq.s   norel
  456.         add.l   d1,(a0)+
  457.         rts
  458. _RelocModule    movem.l    a2-a3/d2-d3,-(sp)
  459.         move.l  a2,d1        ;d1 = ptr to start of module
  460.         bsr.s    relocp
  461.         movea.l 8(a2),a1
  462.         bsr.s    reloci
  463. rel_lp        bsr.s    relocb
  464.         move.l    32(a2),d0    ;extension struct
  465.         beq.s    rel_ex
  466.         move.l    d0,a0
  467.         bsr.s    relocentr    ;ptr to next module
  468.         bsr.s    relocentr    ;InstrExt...
  469.         addq.l    #4,a0        ;skip sizes of InstrExt
  470.         bsr.s    relocentr    ;annotxt
  471.         addq.l    #4,a0        ;annolen
  472.         bsr.s    relocentr    ;InstrInfo
  473.         addq.l    #8,a0
  474.         bsr.s    relocentr    ;rgbtable (not useful for most people)
  475.         addq.l    #4,a0        ;skip channelsplit
  476.         bsr.s    relocentr    ;NotationInfo
  477.         bsr.s    relocentr    ;songname
  478.         addq.l    #4,a0        ;skip song name length
  479.         bsr.s    relocentr    ;MIDI dumps
  480.         bsr.s    relocmdd
  481.         move.l    d0,a0
  482.         move.l    (a0),d0
  483.         beq.s    rel_ex
  484.         move.l    d0,a2
  485.         bsr.s    relocp
  486.         movea.l 8(a2),a1
  487.         bra.s    rel_lp
  488. rel_ex        movem.l    (sp)+,d2-d3/a2-a3
  489.         rts
  490. relocp        lea    8(a2),a0
  491.         bsr.s    relocentr
  492.         addq.l    #4,a0
  493.         bsr.s    relocentr
  494.         addq.l    #4,a0
  495.         bsr.s    relocentr
  496.         addq.l    #4,a0
  497.         bra.s    relocentr
  498. relocb        move.l    16(a2),d0
  499.         beq.s    xlocb
  500.         movea.l    d0,a0
  501.         move.w  504(a1),d0
  502.         subq.b  #1,d0
  503. rebl        bsr.s   relocentr
  504.         dbf     d0,rebl
  505.         cmp.b    #'1',3(a2)    ;test MMD type
  506.         beq.s    relocbi
  507. xlocb        rts
  508. relocmdd    tst.l    -(a0)
  509.         beq.s    xlocmdd
  510.         movea.l    (a0),a0
  511.         move.w    (a0),d0        ;# of msg dumps
  512.         addq.l    #8,a0
  513. mddloop        beq.s    xlocmdd
  514.         bsr    relocentr
  515.         bsr.s    relocdmp
  516.         subq.w    #1,d0
  517.         bra.s    mddloop
  518. xlocmdd        rts
  519. relocdmp    move.l    -4(a0),d3
  520.         beq.s    xlocdmp
  521.         exg.l    a0,d3        ;save
  522.         addq.l    #4,a0
  523.         bsr    relocentr    ;reloc data pointer
  524.         move.l    d3,a0        ;restore
  525. xlocdmp        rts
  526. relocbi        move.w    504(a1),d0
  527.         move.l    a0,a3
  528. biloop        subq.w    #1,d0
  529.         bmi.s    xlocdmp
  530.         move.l    -(a3),a0
  531.         addq.l    #4,a0
  532.         bsr    relocentr    ;BlockInfo ptr
  533.         tst.l    -(a0)
  534.         beq.s    biloop
  535.         move.l    (a0),a0
  536.         bsr    relocentr    ;hldata
  537.         bsr    relocentr    ;block name
  538.         bra.s    biloop
  539.     ENDC
  540.  
  541.  
  542. _ChannelOff:    ;d0 = channel #
  543.         lea    DB,a0
  544.         lea    trackdataptrs-DB(a0),a1
  545.         lsl.b    #2,d0
  546.         adda.w    d0,a1
  547.         lsr.b    #2,d0
  548.         movea.l    (a1),a1
  549.     IFNE    MIDI
  550.         move.b    trk_prevmidin(a1),d1    ;first: is it MIDI??
  551.         beq.s    notcomidi    ;not a midi note
  552.         lea    noteondata-DB(a0),a0
  553. choff_midi:    clr.b    trk_prevmidin(a1)
  554.         move.b    d1,1(a0)
  555.         bmi.s    notamigatrk
  556.         move.b    trk_prevmidich(a1),(a0)    ;prev midi channel
  557.         clr.b    2(a0)
  558.         or.b    #$90,(a0)        ;note off
  559.         moveq    #3,d0
  560.         bra.w    _AddMIDIData
  561.     ENDC
  562. notcomidi:    cmp.b    #4,d0
  563.         bge.s    notamigatrk
  564.     IFNE    SYNTH
  565.         clr.l    trk_synthptr(a1)
  566.         clr.b    trk_synthtype(a1)
  567.     ENDC
  568.         moveq    #1,d1
  569.         lsl.w    d0,d1
  570.         move.w    d1,$dff096
  571. notamigatrk:    rts
  572.  
  573. SoundOff:    move.l    d2,-(sp)
  574.         moveq    #15,d2
  575. SO_loop0    move.l    d2,d0
  576.         bsr.s    _ChannelOff
  577.         dbf    d2,SO_loop0
  578.         clr.l    _module        ;play nothing
  579.         move.l    (sp)+,d2
  580. SO_rts        rts
  581.  
  582. _PlayNote:    ;d7(w) = trk #, d1 = note #, d3(w) = instr # a3 = addr of instr
  583.         move.l    a3,d4
  584.         beq.s    SO_rts
  585.         moveq    #0,d4
  586.         bset    d7,d4    ;d4 is mask for this channel
  587.         movea.l    mmd_smplarr(a2),a0
  588.         add.w    d3,d3            ;d3 = instr.num << 2
  589.         add.w    d3,d3
  590.         move.l    0(a0,d3.w),d5        ;get address of instrument
  591.     IFNE    MIDI
  592.         bne.s    inmem
  593.         tst.b    inst_midich(a3)        ;is MIDI channel set
  594.     ENDC
  595.     IFNE    CHECK
  596.         beq.w    pnote_rts        ; NO!!!
  597.     ENDC
  598. inmem:        add.b    msng_playtransp(a4),d1    ;add play transpose
  599.         add.b    inst_strans(a3),d1    ;and instr. transpose
  600.         cmp.b    #4,d7
  601.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  602.         move.l    d5,a1
  603.     IFNE    SYNTH
  604.         tst.l    d5
  605.         beq.s    stpdma
  606.         tst.b    trk_synthtype(a5)
  607.         ble.s    stpdma        ;prev. type = sample/hybrid
  608.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  609.         beq.s    nostpdma
  610.     ENDC
  611. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  612. nostpdma:
  613.     IFNE    SYNTH
  614.         clr.l    trk_synthptr(a5)
  615.     ENDC
  616. nodmaoff:    subq.b    #1,d1
  617.     IFNE    MIDI
  618.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  619.         beq.s    noprevmidi
  620.         clr.b    trk_prevmidin(a5)
  621.         lea    noteondata+2-DB(a6),a0
  622.         clr.b    (a0)
  623.         move.b    d3,-(a0)
  624.         bmi.s    noprevmidi
  625.         move.b    trk_prevmidich(a5),-(a0) ;prev midi channel
  626.         or.b    #$90,(a0)         ;note off
  627.         move.w    d1,-(sp)
  628.         moveq    #3,d0
  629.         bsr.w    _AddMIDId
  630.         move.w    (sp)+,d1
  631. noprevmidi:
  632.         tst.b    inst_midich(a3)
  633.         bne.w    handleMIDInote
  634.     ENDC
  635.     IFNE    CHECK
  636.         cmp.w    #4,d7        ;track > 3???
  637.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  638.     ENDC
  639. ; handle decay (for tracks 0 - 3 only!!)
  640.     IFNE    HOLD
  641.         clr.b    trk_fadespd(a5)        ;no fade yet..
  642.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  643.     ENDC
  644.         clr.w    trk_vibroffs(a5)    ;clr vibrato/tremolo offset
  645.         or.w    d4,dmaonmsk-DB(a6)
  646.         move.l    d5,a0
  647.     IFNE    SYNTH
  648.         tst.w    4(a0)
  649.         bmi.w    handleSynthnote
  650.         clr.b    trk_synthtype(a5)
  651.     ENDC
  652. tlwtst0:    tst.b    d1
  653.         bpl.s    notenot2low
  654.         add.b    #12,d1    ;note was too low, octave up
  655.         bra.s    tlwtst0
  656. notenot2low:    cmp.b    #62,d1
  657.         ble.s    endpttest
  658.         sub.b    #12,d1    ;note was too high, octave down
  659. endpttest
  660.         moveq    #0,d2
  661.         moveq    #0,d3
  662.     IFNE    IFFMOCT
  663.         move.w    4(a0),d0    ;Soitin-struct in a0
  664.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  665.     ENDC
  666.         lea    _periodtable+32-DB(a6),a1
  667.         move.b    trk_finetune(a5),d2    ;finetune value
  668.         add.b    d2,d2
  669.         add.b    d2,d2        ;multiply by 4...
  670.         ext.w    d2        ;extend
  671.         movea.l    0(a1,d2.w),a1    ;period table address
  672.         move.l    a1,trk_periodtbl(a5)
  673.         add.b    d1,d1
  674.         move.w    0(a1,d1.w),d5 ;put period to d5
  675.         move.l    a0,d0
  676.         addq.l    #6,d0        ;Skip structure
  677.         move.l    (a0),d1        ;length
  678.         add.l    d0,d1        ;sample end pointer
  679.         move.w    inst_repeat(a3),d2
  680.         move.w    inst_replen(a3),d3
  681.     IFNE    IFFMOCT
  682.         bra    gid_setrept
  683. gid_addtable    dc.b    0,6,12,18,24,30
  684. gid_divtable    dc.b    31,7,3,15,63,127
  685. iff5or3oct:    move.l    d7,-(sp)
  686.         moveq    #0,d7
  687.         move.w    d1,d7
  688.         divu    #12,d7    ;octave #
  689.         move.l    d7,d5
  690.         cmp.w    #6,d7    ;if oct > 5, oct = 5
  691.         blt.s    nohioct
  692.         moveq    #5,d7
  693. nohioct        swap    d5    ;note number in this oct (0-11) is in d5
  694.         move.l    (a0),d1
  695.         cmp.w    #6,d0
  696.         ble.s    nounrecit
  697.         moveq    #6,d0
  698. nounrecit    add.b    gid_addtable-1(pc,d0.w),d7
  699.         move.b    gid_divtable-1(pc,d0.w),d0
  700.         divu    d0,d1    ;get length of the highest octave
  701.         swap    d1
  702.         clr.w    d1
  703.         swap    d1
  704.         move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  705.         move.w    inst_repeat(a3),d2
  706.         move.w    inst_replen(a3),d3
  707.         moveq    #0,d6
  708.         move.b    shiftcnt(pc,d7.w),d6
  709.         lsl.w    d6,d2
  710.         lsl.w    d6,d3
  711.         lsl.w    d6,d1
  712.         move.b    mullencnt(pc,d7.w),d6
  713.         mulu    d6,d0        ;offset of this oct from 1st oct
  714.         add.l    a0,d0        ;add base address to offset
  715.         addq.l    #6,d0        ;skip structure
  716.         add.l    d0,d1
  717.         lea    _periodtable+32-DB(a6),a1
  718.         move.b    trk_finetune(a5),d6
  719.         add.b    d6,d6
  720.         add.b    d6,d6
  721.         ext.w    d6
  722.         movea.l    0(a1,d6.w),a1
  723.         move.l    a1,trk_periodtbl(a5)
  724.         add.b    octstart(pc,d7.w),d5
  725.         add.b    d5,d5
  726.         move.w    0(a1,d5.w),d5
  727.         move.l    (sp)+,d7
  728.         bra.s    gid_setrept
  729. shiftcnt:    dc.b    4,3,2,1,1,0,2,2,1,1,0,0,1,1,0,0,0,0
  730.         dc.b    3,3,2,2,1,0,5,4,3,2,1,0,6,5,4,3,2,1
  731. mullencnt:    dc.b    15,7,3,1,1,0,3,3,1,1,0,0,1,1,0,0,0,0
  732.         dc.b    7,7,3,3,1,0,31,15,7,3,1,0,63,31,15,7,3,1
  733. octstart:    dc.b    12,12,12,12,24,24,0,12,12,24,24,36,0,12,12,24,36,36
  734.         dc.b    0,12,12,24,24,24,12,12,12,12,12,12,12,12,12,12,12,12
  735.     ENDC
  736. gid_setrept    add.l    d2,d2
  737.         add.l    d0,d2        ;rep. start pointer
  738.         cmp.w    #1,d3
  739.         bhi.s    gid_noreplen2
  740.         moveq    #0,d3        ;no repeat
  741.         bra.s    gid_cont
  742. gid_noreplen2    add.l    d3,d3
  743.         add.l    d2,d3        ;rep. end pointer
  744.  
  745. gid_cont    moveq    #0,d4
  746.         move.w    trk_soffset(a5),d4
  747.         add.l    d4,d0
  748.         cmp.l    d0,d1
  749.         bhi.s    pn_nooffsovf
  750.         sub.l    d4,d0
  751. pn_nooffsovf    movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  752.         move.l    d0,(a1)+        ;put it in ac_ptr
  753.         cmp.l    d0,d3
  754.         bhi.s    repeat
  755.  
  756.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  757.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  758.         sub.l    d0,d1
  759.         lsr.l    #1,d1            ;shift length right
  760.         move.w    d1,(a1)+            ;and put to ac_len
  761.         bra.s    retsn1
  762.  
  763. repeat:        move.l    d2,trk_sampleptr(a5)
  764.         move.l    d3,d1
  765.         sub.l    d0,d1
  766.         lsr.l    #1,d1
  767.         move.w    d1,(a1)+    ;ac_len
  768.         sub.l    d2,d3
  769.         lsr.l    #1,d3
  770.         move.w    d3,trk_samplelen(a5)
  771.  
  772. retsn1        move.w    d5,trk_prevper(a5)
  773.     IFNE    SYNTH
  774.         tst.b    trk_synthtype(a5)
  775.         bne.w    hSn2
  776.     ENDC
  777. pnote_rts    rts
  778.  
  779.     IFNE    MIDI
  780. handleMIDInote:
  781.     IFNE    PLAYMMD0
  782.         cmp.b    #'1',3(a2)
  783.         beq.s    plr_mmd1_3
  784.         add.b    #24,d1
  785. plr_mmd1_3
  786.     ENDC
  787.         move.b    trk_prevvol(a5),d2 ;temporarily save the volume
  788.         add.b    d2,d2        ;volume 0 - 63 => 0 - 127
  789.         subq.b    #1,d2        ;if 128 => 127
  790.         bpl.s    hmn_notvolu0
  791.         moveq    #0,d2
  792. hmn_notvolu0
  793.         moveq    #0,d5
  794.         move.b    inst_midich(a3),d5 ;get midi chan of this instrument
  795.         bpl.s    hmn_nosmof    ;bit 7 clear
  796.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  797.         and.b    #$1F,d5        ;clear all flag bits etc...
  798.         bra.s    hmn_smof
  799. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  800. hmn_smof    subq.b    #1,d5        ;from 1-16 to 0-15
  801.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  802.  
  803.         move.b    inst_midipreset(a3),d0    ;get preset #
  804.         beq.s    nochgpres    ;zero = no preset
  805.         lea    prevmidicpres-DB(a6),a1
  806.         adda.w    d5,a1
  807.         cmp.b    (a1),d0        ;is this previous preset ??
  808.         beq.s    nochgpres    ;yes...no need to change
  809.         move.b    d0,(a1)        ;save preset to prevmidicpres
  810.         subq.b    #1,d0        ;sub 1 to get 0 - 127
  811.         lea    preschgdata+1-DB(a6),a0
  812.         move.b    d0,(a0)        ;push the number to second byte
  813.         move.b    #$c0,-(a0)    ;command: $C
  814.         or.b    d5,(a0)        ;"or" midi channel
  815.         moveq    #2,d0
  816.         move.w    d1,-(sp)
  817.         bsr.w    _AddMIDId
  818.         move.w    (sp)+,d1
  819.         tst.b    d2
  820.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  821.  
  822. nochgpres    lea    bytesinnotebuff-DB(a6),a0
  823.         movea.l    a0,a1
  824.         adda.w    (a0)+,a0
  825.         or.b    #$90,d5        ;MIDI: Note on
  826.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  827.         move.b    d1,(a0)+    ;MIDI msg note #
  828.         move.b    d2,(a0)        ;MIDI msg volume
  829.         beq.s    hmn_suppress    ;vol = 0 -> no note
  830.         addq.w    #3,(a1)
  831.         rts
  832. hmn_suppress    st    trk_prevmidin(a5)
  833.         rts
  834.     ENDC
  835.  
  836.     IFNE    SYNTH
  837. handleSynthnote:
  838.         move.b    d1,trk_prevnote2(a5)
  839.         move.l    a0,trk_synthptr(a5)
  840.         cmp.w    #-2,4(a0)    ;HYBRID??
  841.         bne.s    hSn_nossn
  842.         st    trk_synthtype(a5)
  843.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  844.         bra.w    tlwtst0        ;go and play it
  845. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  846.         lea    _periodtable+32-DB(a6),a1
  847.         move.b    trk_finetune(a5),d0    ;finetune value
  848.         add.b    d0,d0
  849.         add.b    d0,d0        ;multiple by 4...
  850.         ext.w    d0        ;extend
  851.         movea.l    0(a1,d0.w),a1    ;period table address
  852.         suba.w    #48,a1
  853.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  854.         add.w    d1,d1
  855.         move.w    0(a1,d1.w),d1
  856.         move.w    d1,trk_prevper(a5)
  857.         clr.l    trk_sampleptr(a5)
  858. hSn2:        lea    trk_arpgoffs(a5),a1
  859.         clr.l    (a1)+
  860.         clr.l    (a1)+
  861.         clr.l    (a1)+
  862.         clr.l    (a1)+
  863.         clr.l    (a1)+
  864.         clr.l    (a1)+
  865.         move.l    #sinetable,(a1)+
  866.         clr.w    (a1)+
  867.         movea.l    trk_synthptr(a5),a0
  868.                 move.w    18(a0),(a1)+
  869.                 clr.b    (a1)
  870.                 cmp.b    #$E,trk_cmd(a5)
  871.                 bne.s    hSn_nocmdE
  872.                 move.b    trk_cmdqual(a5),trk_wfcmd+1(a5)
  873. hSn_nocmdE    moveq    #64,d4
  874.         rts
  875.  
  876. synth_start    move.w    trk_prevper(a5),d5
  877. synth_start2    move.l    a3,-(sp)    ;d0 = SynthPtr
  878.         move.l    d0,a0
  879.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  880.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  881.         bgt.w    synth_wftbl        ;not 0...go to waveform
  882.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  883.         move.b    trk_volchgspd(a5),d0    ;volume change??
  884.         beq.s    synth_nochgvol        ;no.
  885.         add.b    trk_synvol(a5),d0    ;add previous volume
  886.         bpl.s    synth_voln2l        ;not negative
  887.         moveq    #0,d0            ;was negative => 0
  888. synth_voln2l    cmp.b    #$40,d0            ;too high??
  889.         ble.s    synth_voln2h        ;not 2 high.
  890.         moveq    #$40,d0            ;was 2 high => 64
  891. synth_voln2h    move.b    d0,trk_synvol(a5)    ;remember new...
  892. synth_nochgvol    move.l    trk_envptr(a5),d1    ;envelope pointer
  893.         beq.s    synth_novolenv
  894.         movea.l    d1,a1
  895.         move.b    (a1)+,d0
  896.         add.b    #128,d0
  897.         lsr.b    #2,d0
  898.         move.b    d0,trk_synvol(a5)
  899.         addq.b    #1,trk_envcount(a5)
  900.         bpl.s    synth_endenv
  901.         clr.b    trk_envcount(a5)
  902.         move.l    trk_envrestart(a5),a1
  903. synth_endenv    move.l    a1,trk_envptr(a5)
  904. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  905.         tst.b    trk_volwait(a5)        ;WAI(t) active
  906.         beq.s    synth_getvolcmd        ;no
  907.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  908.         ble.s    synth_getvolcmd        ;0 => continue
  909.         bra.w    synth_wftbl        ;> 0 => still wait
  910. synth_inccnt    addq.b    #1,d0
  911. synth_getvolcmd    addq.b    #1,d0            ;advance pointer
  912.         move.b    21(a0,d0.w),d1        ;get command
  913.         bmi.s    synth_cmd        ;negative = command
  914.         move.b    d1,trk_synvol(a5)    ;set synthvol
  915.         bra.w    synth_endvol        ;end of volume executing
  916. synth_cmd    and.w    #$000f,d1
  917.         add.b    d1,d1
  918.         move.w    synth_vtbl(pc,d1.w),d1
  919.         jmp    syv(pc,d1.w)
  920. synth_vtbl    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  921.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  922.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  923.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  924.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  925. syv
  926. syv_fe        move.b    22(a0,d0.w),d0        ;JMP
  927.         bra.s    synth_getvolcmd
  928. syv_f0        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  929.         bra.s    synth_inccnt
  930. syv_f1        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  931.         addq.b    #1,d0
  932.         bra.s    synth_endvol
  933. syv_f3        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  934.         bra.s    synth_inccnt
  935. syv_f2        move.b    22(a0,d0.w),d1
  936.         neg.b    d1
  937.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  938.         bra.s    synth_inccnt
  939. syv_fa        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  940.         clr.b    trk_wfwait(a5)
  941.         bra.s    synth_inccnt
  942. syv_f4        move.b    22(a0,d0.w),d1
  943.         bsr.s    synth_getwf
  944.         clr.l    trk_envrestart(a5)
  945. syv_f4end    move.l    a1,trk_envptr(a5)
  946.         clr.b    trk_envcount(a5)
  947.         bra.w    synth_inccnt
  948. syv_f5        move.b    22(a0,d0.w),d1
  949.         bsr.s    synth_getwf
  950.         move.l    a1,trk_envrestart(a5)
  951.         bra.s    syv_f4end
  952. syv_f6        clr.l    trk_envptr(a5)
  953.         bra.w    synth_getvolcmd
  954. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  955.         add.w    d1,d1    ;create index
  956.         add.w    d1,d1
  957.         lea    278(a0),a1
  958.         adda.w    d1,a1
  959.         movea.l    (a1),a1        ;get wform address
  960.         addq.l    #2,a1        ;skip length
  961.         rts
  962. syv_ff        subq.b    #1,d0
  963. synth_endvol    move.w    d0,trk_volcmd(a5)
  964. synth_wftbl    move.b    trk_synvol(a5),trk_prevvol(a5)
  965.         adda.w    #158,a0
  966.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  967.         bgt.w    synth_arpeggio        ;not yet...
  968.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  969.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  970.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  971.         beq.s    synth_tstwfwai        ;0 = no change
  972. wytanwet    add.w    trk_perchg(a5),d1    ;add value to current change
  973.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  974. synth_tstwfwai    tst.b    trk_wfwait(a5)        ;WAI ??
  975.         beq.s    synth_getwfcmd        ;not waiting...
  976.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  977.         beq.s    synth_getwfcmd        ;waiting finished
  978.         bra.w    synth_arpeggio        ;still sleep...
  979. synth_incwfc    addq.b    #1,d0
  980. synth_getwfcmd    addq.b    #1,d0            ;advance position counter
  981.         move.b    -9(a0,d0.w),d1        ;get command
  982.         bmi.s    synth_wfcmd        ;negative = command
  983.         ext.w    d1
  984.         add.w    d1,d1
  985.         add.w    d1,d1
  986.         movea.l    120(a0,d1.w),a1
  987.         move.w    (a1)+,ac_len(a3)    ;push waveform length
  988.         move.l    a1,ac_ptr(a3)        ;and the new pointer
  989.         bra.w    synth_wfend        ;no new commands now...
  990. synth_wfcmd    and.w    #$000f,d1        ;get the right nibble
  991.         add.b    d1,d1            ;* 2
  992.         move.w    synth_wfctbl(pc,d1.w),d1
  993.         jmp    syw(pc,d1.w)        ;jump to command
  994. synth_wfctbl    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  995.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  996.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  997.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  998. syw
  999. syw_f7        move.b    -8(a0,d0.w),d1
  1000.         ext.w    d1
  1001.         add.w    d1,d1
  1002.         add.w    d1,d1
  1003.         movea.l    120(a0,d1.w),a1
  1004.         addq.l    #2,a1
  1005.         move.l    a1,trk_synvibwf(a5)
  1006.         bra.s    synth_incwfc
  1007. syw_fe        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  1008.         bra.s    synth_getwfcmd
  1009. syw_fc        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  1010.         move.w    d0,trk_arpgoffs(a5)
  1011. synth_findare    addq.b    #1,d0
  1012.         tst.b    -9(a0,d0.w)
  1013.         bpl.s    synth_findare
  1014.         bra.s    synth_getwfcmd
  1015. syw_f0        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  1016.         bra    synth_incwfc
  1017. syw_f1        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  1018.         addq.b    #1,d0
  1019.         bra.s    synth_wfend
  1020. syw_f4        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  1021.         bra.w    synth_incwfc
  1022. syw_f5        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  1023.         addq.b    #1,trk_synthvibspd+1(a5)
  1024.         bra.w    synth_incwfc
  1025. syw_f2        moveq    #0,d1            ;set slide down
  1026.         move.b    -8(a0,d0.w),d1
  1027. synth_setsld    move.w    d1,trk_wfchgspd(a5)
  1028.         bra.w    synth_incwfc
  1029. syw_f3        move.b    -8(a0,d0.w),d1        ;set slide up
  1030.         neg.b    d1
  1031.         ext.w    d1
  1032.         bra.s    synth_setsld
  1033. syw_f6        clr.w    trk_perchg(a5)        ;reset period
  1034.         move.w    trk_prevper(a5),d5
  1035.         bra.w    synth_getwfcmd
  1036. syw_fa        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  1037.         clr.b    trk_volwait(a5)
  1038.         bra.w    synth_incwfc
  1039. syw_ff        subq.b    #1,d0        ;pointer = END - 1
  1040. synth_wfend    move.w    d0,trk_wfcmd(a5)
  1041. synth_arpeggio    move.w    trk_arpgoffs(a5),d0
  1042.         beq.s    synth_vibrato
  1043.         moveq    #0,d1
  1044.         move.b    -8(a0,d0.w),d1
  1045.         add.b    trk_prevnote2(a5),d1
  1046.         movea.l    trk_periodtbl(a5),a1    ;get period table
  1047.         add.w    d1,d1
  1048.         move.w    0(a1,d1.w),d5
  1049.         addq.b    #1,d0
  1050.         tst.b    -8(a0,d0.w)
  1051.         bpl.s    synth_noarpres
  1052.         move.w    trk_arpsoffs(a5),d0
  1053. synth_noarpres    move.w    d0,trk_arpgoffs(a5)
  1054. synth_vibrato    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  1055.         beq.s    synth_rts        ;0 => no vibrato
  1056.         move.w    trk_synviboffs(a5),d0    ;get offset
  1057.         lsr.w    #4,d0            ;/ 16
  1058.         and.w    #$1f,d0            ;sinetable offset (0-31)
  1059.         movea.l trk_synvibwf(a5),a0
  1060.         move.b    0(a0,d0.w),d0       ;get a byte
  1061.         ext.w    d0            ;to word
  1062.         muls    d1,d0            ;amplify (* depth)
  1063.         asr.w    #8,d0            ;and divide by 64
  1064.         add.w    d0,d5            ;add vibrato...
  1065.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  1066.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  1067. synth_rts    add.w    trk_perchg(a5),d5
  1068.         cmp.w    #113,d5            ;overflow??
  1069.         bge.s    synth_pern2h
  1070.         moveq    #113,d1
  1071. synth_pern2h    move.l    (sp)+,a3
  1072.         rts
  1073.     ENDC
  1074. sinetable    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  1075.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  1076.         dc.b    -106,-90,-71,-49,-25,0
  1077.                 even
  1078. _IntHandler:    movem.l    d2-d7/a2-a6,-(sp)
  1079.         movea.l    a1,a6        ;get data base address
  1080.         tst.b    bpmcounter-DB(a6)
  1081.         bmi.s    plr_nobpm
  1082.         subq.b    #1,bpmcounter-DB(a6)
  1083.         ble.s    plr_bpmcnt0
  1084.         bra.w    plr_exit
  1085. plr_bpmcnt0    move.b    #4,bpmcounter-DB(a6)
  1086. plr_nobpm    movea.l    _module-DB(a6),a2
  1087.         move.l    a2,d0
  1088.         beq.w    plr_exit
  1089.     IFNE    MIDI
  1090.         clr.b    lastcmdbyte-DB(a6)    ;no MIDI optimization
  1091.     ENDC
  1092.         tst.w    mmd_pstate(a2)
  1093.         beq.w    plr_exit
  1094.     IFNE    MIDI
  1095.         clr.l    dmaonmsk-DB(a6)
  1096.     ENDC
  1097.     IFEQ    MIDI
  1098.         clr.w    dmaonmsk-DB(a6)
  1099.     ENDC
  1100.         movea.l    mmd_songinfo(a2),a4
  1101.         moveq    #0,d3
  1102.         move.b    mmd_counter(a2),d3
  1103.         addq.b    #1,d3
  1104.         cmp.b    msng_tempo2(a4),d3
  1105.         bge.s    plr_pnewnote    ;play new note
  1106.         move.b    d3,mmd_counter(a2)
  1107.         bne.w    plr_fxtime    ;do just fx
  1108. ; --- new note!!
  1109. plr_pnewnote:    clr.b    mmd_counter(a2)
  1110.         tst.w    blkdelay-DB(a6)
  1111.         beq.s    plr_noblkdelay
  1112.         subq.w    #1,blkdelay-DB(a6)
  1113.         bne.w    nonewnote
  1114. ; --- now start to play it
  1115. plr_noblkdelay    move.w    mmd_pblock(a2),d0
  1116.         movea.l    mmd_blockarr(a2),a0
  1117.         add.w    d0,d0
  1118.         add.w    d0,d0
  1119.         movea.l    0(a0,d0.w),a1    ;block...
  1120.         move.w    mmd_pline(a2),d0
  1121.     IFNE    PLAYMMD0
  1122.         cmp.b    #'1',3(a2)    ;check ID type
  1123.         beq.s    plr_mmd1_0
  1124.         move.w    d0,d1
  1125.         add.w    d0,d0
  1126.         add.w    d1,d0        ;d0 = d0 * 3
  1127.         clr.l    numtracks-DB(a6)
  1128.         move.b    (a1)+,numtracks+1-DB(a6)
  1129.         move.b    (a1),numlines+1-DB(a6)
  1130.         mulu    numtracks-DB(a6),d0
  1131.         pea    1(a1,d0.w)
  1132.         bra.s    plr_begloop
  1133. plr_mmd1_0
  1134.     ENDC
  1135.         add.w    d0,d0
  1136.         add.w    d0,d0        ;d0 = d0 * 4
  1137.         mulu    (a1),d0        ;numtracks * d0
  1138.         pea    8(a1,d0.l)    ;address of the current note
  1139.         move.w    (a1)+,numtracks-DB(a6)
  1140.         move.w    (a1),numlines-DB(a6)
  1141. plr_begloop    moveq    #0,d7        ;number of track
  1142.         moveq    #0,d4
  1143.         pea    trackdataptrs-DB(a6)
  1144. plr_loop0:    moveq    #0,d5
  1145.         move.l    (sp),a1
  1146.         movea.l    (a1)+,a5    ;get address of this track's struct
  1147.         move.l    a1,(sp)
  1148. ; ---------------- get the note numbers
  1149.         moveq    #0,d3
  1150.         move.l    4(sp),a1
  1151.     IFNE    PLAYMMD0
  1152.         cmp.b    #'1',3(a2)
  1153.         beq.s    plr_mmd1_1
  1154.         move.b    (a1)+,d5
  1155.         move.b    (a1)+,d6
  1156.         move.b    (a1)+,trk_cmdqual(a5)
  1157.         move.b    d6,d3
  1158.         and.w    #$0F,d6
  1159.         lsr.b    #4,d3
  1160.         bclr    #7,d5
  1161.         beq.s    plr_bseti4
  1162.         bset    #4,d3
  1163. plr_bseti4    bclr    #6,d5
  1164.         beq.s    plr_bseti5
  1165.         bset    #5,d3
  1166. plr_bseti5    bra.s    plr_nngok
  1167. plr_mmd1_1
  1168.     ENDC
  1169.         move.b    (a1)+,d5    ;get the number of this note
  1170.         bpl.s    plr_nothinote
  1171.         moveq    #0,d5
  1172. plr_nothinote    move.b    (a1)+,d3    ;instrument number
  1173.         move.b    (a1)+,d6    ;cmd number
  1174.         and.w    #$1F,d6        ;recognize only cmds 00 - 1F
  1175.         move.b    (a1)+,trk_cmdqual(a5)    ;databyte (qualifier)
  1176. plr_nngok    move.l    a1,4(sp)
  1177. ; ---------------- check if there's an instrument number
  1178.         and.w    #$3F,d3
  1179.         beq.s    noinstnum
  1180. ; ---------------- finally, save the number
  1181.         subq.b    #1,d3
  1182.         move.b    d3,trk_previnstr(a5) ;remember instr. number!
  1183.     IFNE    HOLD
  1184.         lea    holdvals-DB(a6),a0
  1185.         adda.w    d3,a0
  1186.         move.b    (a0),trk_inithold(a5)
  1187.         move.b    63(a0),trk_initdecay(a5)
  1188.         move.b    126(a0),trk_finetune(a5)
  1189.     ENDC
  1190.         asl.w    #3,d3
  1191.         lea    0(a4,d3.w),a3    ;a3 contains now address of it
  1192.         move.l    a3,trk_previnstra(a5)
  1193.         moveq    #0,d0
  1194. ; ---------------- get volume and make it relative (1 - 100 %)
  1195.     IFNE    RELVOL
  1196.         move.b    inst_svol(a3),d0
  1197.         mulu    trk_trackvol(a5),d0
  1198.         lsr.w    #8,d0
  1199.         move.b    d0,trk_prevvol(a5) ;vol of this instr
  1200.     ENDC
  1201.     IFEQ    RELVOL
  1202.         move.b    inst_svol(a3),trk_prevvol(a5)
  1203.     ENDC
  1204. ; ---------------- remember transpose
  1205.         move.b    inst_strans(a3),trk_stransp(a5)
  1206.         clr.w    trk_soffset(a5)        ;sample offset
  1207. ; ---------------- check the commands
  1208. noinstnum    move.b    d6,trk_cmd(a5)    ;save the effect number
  1209.         beq.w    fx    ;no effect
  1210.         move.b    trk_cmdqual(a5),d4    ;get qualifier...
  1211.         add.b    d6,d6    ;* 2
  1212.         move.w    f_table(pc,d6.w),d0
  1213.         jmp    fst(pc,d0.w)
  1214. f_table        dc.w    fx-fst,fx-fst,fx-fst,f_03-fst,fx-fst,fx-fst,fx-fst,fx-fst
  1215.         dc.w    f_08-fst,f_09-fst,fx-fst,f_0b-fst,f_0c-fst,fx-fst,f_0e-fst,f_0f-fst
  1216.         dc.w    fx-fst,fx-fst,fx-fst,fx-fst,fx-fst,f_15-fst,f_16-fst,fx-fst
  1217.         dc.w    fx-fst,f_19-fst,fx-fst,fx-fst,f_1c-fst,f_1d-fst,fx-fst,f_1f-fst
  1218. fst
  1219. ; ---------------- tempo (F)
  1220. f_0f        tst.b    d4        ;test effect qual..
  1221.         beq    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  1222.         cmp.b    #$f0,d4        ;..is zero, go to next block
  1223.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  1224. ; ---------------- just an ordinary "change tempo"-request
  1225.     IFNE    uCIAB
  1226.         moveq    #0,d0        ;will happen!!!
  1227.         move.b    d4,d0
  1228.         move.w    d0,msng_deftempo(a4)
  1229.         bsr    _SetTempo    ;change The Tempo
  1230.     ENDC
  1231.         bra.w    fx
  1232. ; ---------------- no, it was FFx, something special will happen!!
  1233. fx0fspecial:    cmp.b    #$f2,d4
  1234.         bne.s    isfxfe
  1235. ; ---------------- FF2 (or 1Fxx)
  1236. f_1f        move.b    d5,(a5)    ; save the note number
  1237.         moveq    #0,d5    ; clear the number for awhile
  1238.     IFNE    HOLD
  1239.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1240.         bne.w    plr_endloop0        ;not 0 -> OK
  1241.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1242.     ENDC
  1243.         bra.w    plr_endloop0
  1244. isfxfe:        cmp.b    #$fe,d4
  1245.         bne.s    notcmdfe
  1246. ; ---------------- it was FFE, stop playing
  1247.         clr.w    mmd_pstate(a2)
  1248.     IFNE    uCIAB
  1249.         movea.l    craddr-DB(a6),a0
  1250.         bclr    #0,(a0)
  1251.     ENDC
  1252.         bsr.w    SoundOff
  1253.         addq.l    #8,sp
  1254.         bra.w    plr_exit
  1255. notcmdfe:    cmp.b    #$fd,d4 ;change period
  1256.         bne.s    isfxff
  1257. ; ---------------- FFD, change the period, don't replay the note
  1258.     IFNE    CHECK
  1259.         cmp.w    #4,d7
  1260.         bge.w    fx
  1261.     ENDC
  1262.         movea.l    trk_periodtbl(a5),a0
  1263.         subq.b    #1,d5
  1264.         bmi.w    plr_endloop0
  1265.         add.b    d5,d5
  1266.         move.w    0(a0,d5.w),trk_prevper(a5)
  1267.         moveq    #0,d5
  1268.         bra.w    fx
  1269. isfxff:        cmp.b    #$ff,d4
  1270.         bne.w    fx
  1271.         move.w    d7,d0
  1272.         bsr.w    _ChannelOff
  1273.         bra.w    fx
  1274. ; ---------------- F00, called Pattern Break in ST
  1275. fx0fchgblck:    move.b    #1,nextblock-DB(a6)
  1276.         bra.w    fx
  1277. ; ---------------- was not Fxx
  1278. f_0e        cmp.b    #3,d7
  1279.         bgt.w    fx
  1280.         move.b    d4,trk_wfcmd+1(a5) ;set waveform command position ptr
  1281.         bra.w    fx
  1282. ; ---------------- change volume
  1283. f_0c        move.b    d4,d0
  1284.         bpl.s    plr_nosetdefvol
  1285.         and.b    #$7F,d0
  1286.     IFNE    CHECK
  1287.         cmp.b    #64,d0
  1288.         bgt.s    go_nocmd
  1289.     ENDC
  1290.         moveq    #0,d1
  1291.         move.b    trk_previnstr(a5),d1
  1292.         asl.w    #3,d1
  1293.         move.b    d0,inst_svol(a4,d1.w)
  1294.         bra.s    plr_setvol
  1295. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  1296.         bne.s    volhex
  1297.         lsr.b    #4,d0        ;get number from left
  1298.         mulu    #10,d0        ;number of tens
  1299.         move.b    d4,d1        ;get again
  1300.         and.b    #$0f,d1        ;this time don't get tens
  1301.         add.b    d1,d0        ;add them
  1302. volhex:
  1303.     IFNE    CHECK
  1304.         cmp.b    #64,d0
  1305.         bhi.s    go_nocmd
  1306.     ENDC
  1307. plr_setvol
  1308.     IFNE    RELVOL
  1309.         mulu    trk_trackvol(a5),d0
  1310.         lsr.w    #8,d0
  1311.     ENDC
  1312.         move.b    d0,trk_prevvol(a5)
  1313. go_nocmd    bra.w    fx
  1314. ; ---------------- tempo2 change??
  1315. f_09
  1316.     IFNE    CHECK
  1317.         and.b    #$1F,d4
  1318.         bne.s    fx9chk
  1319.         moveq    #$20,d4
  1320.     ENDC
  1321. fx9chk:        move.b    d4,msng_tempo2(a4)
  1322.         bra    fx
  1323. ; ---------------- finetune
  1324. f_15
  1325.     IFNE    CHECK
  1326.         cmp.b    #7,d4
  1327.         bgt    fx
  1328.         cmp.b    #-8,d4
  1329.         blt    fx
  1330.     ENDC
  1331.         move.b    d4,trk_finetune(a5)
  1332.         bra    fx
  1333. ; ---------------- repeat loop
  1334. f_16        tst.b    d4
  1335.         bne.s    plr_dorpt
  1336.         move.w    mmd_pline(a2),rptline-DB(a6)
  1337.         bra    fx
  1338. plr_dorpt    tst.w    rptcounter-DB(a6)
  1339.         beq.s    plr_newrpt
  1340.         subq.w    #1,rptcounter-DB(a6)
  1341.         beq    fx
  1342.         bra.s    plr_setrptline
  1343. plr_newrpt    move.b    d4,rptcounter+1-DB(a6)
  1344. plr_setrptline    move.w    rptline-DB(a6),d0
  1345.         addq.w    #1,d0
  1346.         move.w    d0,nextblockline-DB(a6)
  1347.         bra    fx
  1348. ; ---------------- preset change
  1349. f_1c
  1350.     IFNE    CHECK
  1351.         cmp.b    #$80,d4
  1352.         bhi    fx
  1353.     ENDC
  1354.         moveq    #0,d1
  1355.         move.b    trk_previnstr(a5),d1
  1356.         asl.w    #3,d1
  1357.         move.b    d4,inst_midipreset(a4,d1.w)    ;set MIDI preset
  1358.         bra.s    fx
  1359. ; ---------------- note off time set??
  1360. f_08
  1361.     IFNE    HOLD
  1362.         move.b    d4,d0
  1363.         lsr.b    #4,d4        ;extract left  nibble
  1364.         and.b    #$0f,d0        ; "   "  right  "  "
  1365.         move.b    d4,trk_initdecay(a5)    ;left = decay
  1366.         move.b    d0,trk_inithold(a5)    ;right = hold
  1367.     ENDC
  1368.         bra.s    fx
  1369. ; ---------------- sample begin offset
  1370. f_19        lsl.w    #8,d4
  1371.         move.w    d4,trk_soffset(a5)
  1372.         bra.s    fx
  1373. ; ---------------- cmd Bxx, "position jump"
  1374. f_0b
  1375.     IFNE    CHECK
  1376.         cmp.w    msng_songlen(a4),d4
  1377.         bhi.s    fx
  1378.     ENDC
  1379.         move.w    d4,mmd_pseqnum(a2)
  1380.         st    nextblock-DB(a6)    ; = 1
  1381.         bra.s    fx
  1382. ; ---------------- cmd 1Dxx, jump to next seq, line # specified
  1383. f_1d        move.w    #$1ff,nextblock-DB(a6)
  1384.         addq.w    #1,d4
  1385.         move.w    d4,nextblockline-DB(a6)
  1386.         bra.s    fx
  1387. ; ---------------- try portamento (3)
  1388. f_03
  1389.     IFNE    CHECK
  1390.         cmp.w    #4,d7
  1391.         bge.s    plr_endloop0
  1392.     ENDC
  1393.         subq.b    #1,d5        ;subtract note number
  1394.         bmi.s    plr_setfx3spd    ;0 -> set new speed
  1395. plr_fx3note:    movea.l    trk_periodtbl(a5),a0
  1396.         add.b    msng_playtransp(a4),d5    ;play transpose
  1397.         add.b    trk_stransp(a5),d5    ;and instrument transpose
  1398.         bmi.s    plr_endloop0
  1399.         add.w    d5,d5
  1400.         move.w    0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
  1401. plr_setfx3spd:    tst.b    d4        ;qual??
  1402.         beq.s    plr_endloop0    ;0 -> do nothing
  1403.         move.b    d4,trk_prevportspd(a5)    ;store speed
  1404.         bra.s    plr_endloop0        ;don't play this one
  1405. ; ---------------- play or not to play??
  1406. fx        tst.b    d5            ;play a note?
  1407.         beq.s    plr_endloop0        ;no.
  1408. ; ---------------- play
  1409.         move.b    d5,(a5)
  1410.         move.w    d5,d1
  1411.         moveq    #0,d3
  1412.         move.b    trk_previnstr(a5),d3    ;instr #
  1413.         movea.l    trk_previnstra(a5),a3    ;instr data address
  1414.     IFNE    HOLD
  1415.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  1416.         bne.s    plr_nohold0        ;not 0 -> OK
  1417.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  1418.     ENDC
  1419. ; ---------------- and finally:
  1420. plr_nohold0    bsr    _PlayNote
  1421. ; ---------------- end of loop: handle next track, or quit
  1422. plr_endloop0:    addq.b    #1,d7
  1423.         cmp.w    numtracks-DB(a6),d7
  1424.         blt.w    plr_loop0
  1425.         addq.l    #8,sp            ;trackdataptrs / note ptr
  1426. ; and advance song pointers
  1427.         lea    nextblock-DB(a6),a3
  1428.         move.w    nextblockline-DB(a6),d1
  1429.         beq.s    plr_advlinenum
  1430.         clr.w    nextblockline-DB(a6)
  1431.         subq.w    #1,d1
  1432.         bra.s    plr_linenumset
  1433. plr_advlinenum    move.w    mmd_pline(a2),d1    ;get current line #
  1434.         addq.w    #1,d1            ;advance line number
  1435. plr_linenumset    cmp.w    numlines-DB(a6),d1     ;advance block?
  1436.         bhi.s    plr_chgblock        ;yes.
  1437.         tst.b    (a3)            ;command F00/1Dxx?
  1438.         beq.s    plr_nochgblock        ;no, don't change block
  1439. plr_chgblock    tst.b    nxtnoclrln-DB(a6)
  1440.         bne.s    plr_noclrln
  1441.         moveq    #0,d1            ;clear line number
  1442. plr_noclrln    tst.w    mmd_pstate(a2)        ;play block or play song
  1443.         bpl.s    plr_nonewseq        ;play block only...
  1444.         move.w    mmd_pseqnum(a2),d0    ;get play sequence number
  1445.         tst.b    (a3)
  1446.         bmi.s    plr_noadvseq        ;Bxx sets nextblock to -1
  1447.         addq.w    #1,d0            ;advance sequence number
  1448. plr_noadvseq    cmp.w    msng_songlen(a4),d0    ;is this the highest seq number??
  1449.         blt.s    plr_notagain        ;no.
  1450.         moveq    #0,d0            ;yes: restart song
  1451. plr_notagain    move.b    d0,mmd_pseqnum+1(a2)    ;remember new playseq-#
  1452.         lea    msng_playseq(a4),a0    ;offset of sequence table
  1453.         move.b    0(a0,d0.w),d0        ;get number of the block
  1454.     IFNE    CHECK
  1455.         cmp.w    msng_numblocks(a4),d0    ;beyond last block??
  1456.         blt.s    plr_nolstblk        ;no..
  1457.         moveq    #0,d0            ;play block 0
  1458.     ENDC
  1459. plr_nolstblk    move.b    d0,mmd_pblock+1(a2)    ;store block number
  1460. plr_nonewseq    clr.w    (a3)             ;clear this if F00 set it
  1461. plr_nochgblock    move.w    d1,mmd_pline(a2)    ;set new line number
  1462.  
  1463.     IFNE    HOLD
  1464.         lea    trackdataptrs-DB(a6),a5
  1465.         movea.l    mmd_blockarr(a2),a0
  1466.         move.w    mmd_pblock(a2),d0
  1467.         add.w    d0,d0
  1468.         add.w    d0,d0
  1469.         movea.l    0(a0,d0.w),a1    ;block...
  1470.         move.w    mmd_pline(a2),d0
  1471.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  1472.     IFNE    PLAYMMD0
  1473.         cmp.b    #'1',3(a2)
  1474.         beq.s    plr_mmd1_2
  1475.         move.b    (a1),d7            ;# of tracks
  1476.         move.w    d0,d1
  1477.         add.w    d0,d0    ;d0 * 2
  1478.         add.w    d1,d0    ;+ d0 = d0 * 3
  1479.         mulu    d7,d0
  1480.         lea    2(a1,d0.w),a3
  1481.         subq.b    #1,d7
  1482. plr_chkholdb    movea.l    (a5)+,a1        ;track data
  1483.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1484.         bmi.s    plr_holdendb        ;no.
  1485.         move.b    (a3),d1            ;get the 1st byte..
  1486.         bne.s    plr_hold1b
  1487.         move.b    1(a3),d1
  1488.         and.b    #$f0,d1
  1489.         beq.s    plr_holdendb        ;don't hold
  1490.         bra.s    plr_hold2b
  1491. plr_hold1b    and.b    #$3f,d1            ;note??
  1492.         beq.s    plr_hold2b        ;no, cont hold..
  1493.         move.b    1(a3),d1
  1494.         and.b    #$0f,d1            ;get cmd
  1495.         subq.b    #3,d1            ;is there command 3 (slide)
  1496.         bne.s    plr_holdendb        ;no -> end holding
  1497. plr_hold2b    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1498. plr_holdendb    addq.l    #3,a3        ;next note
  1499.         dbf    d7,plr_chkholdb
  1500.         bra.s    nonewnote
  1501. plr_mmd1_2
  1502.     ENDC
  1503.         move.w    (a1),d7        ;# of tracks
  1504.         add.w    d0,d0
  1505.         add.w    d0,d0    ;d0 = d0 * 4
  1506.         mulu    d7,d0
  1507.         lea    8(a1,d0.l),a3
  1508.         subq.b    #1,d7
  1509. plr_chkhold    movea.l    (a5)+,a1        ;track data
  1510.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1511.         bmi.s    plr_holdend        ;no.
  1512.         move.b    (a3),d1            ;get the 1st byte..
  1513.         bne.s    plr_hold1
  1514.         move.b    1(a3),d0
  1515.         and.b    #$3F,d0
  1516.         beq.s    plr_holdend        ;don't hold
  1517.         bra.s    plr_hold2
  1518. plr_hold1    and.b    #$7f,d1            ;note??
  1519.         beq.s    plr_hold2        ;no, cont hold..
  1520.         move.b    2(a3),d1
  1521.         subq.b    #3,d1            ;is there command 3 (slide)
  1522.         bne.s    plr_holdend        ;no -> end holding
  1523. plr_hold2    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1524. plr_holdend    addq.l    #4,a3        ;next note
  1525.         dbf    d7,plr_chkhold
  1526.     ENDC
  1527. nonewnote    moveq    #0,d3
  1528.         move.b    mmd_counter(a2),d3
  1529. plr_fxtime    lea    trackdataptrs-DB(a6),a3
  1530.         moveq    #0,d7    ;clear track count
  1531. plr_loop1    movea.l    (a3)+,a5
  1532.         moveq    #0,d4
  1533.         moveq    #0,d5
  1534.         moveq    #0,d6
  1535.         move.b    trk_cmd(a5),d6    ;get the fx number
  1536.         move.b    trk_cmdqual(a5),d4    ;and the last 2 #'s
  1537.     IFNE    MIDI
  1538.         tst.b    trk_prevmidin(a5)    ;is it MIDI??
  1539.         bne.w    midicmds
  1540.     ENDC
  1541.         cmp.w    #4,d7
  1542.     IFNE    MIDI
  1543.         bge.w    midicmds    ;no non-MIDI effects in tracks 4 - 15
  1544.     ENDC
  1545.     IFEQ    MIDI
  1546.         bge.w    endl
  1547.     ENDC
  1548.     IFNE    HOLD
  1549.         tst.b    trk_noteoffcnt(a5)
  1550.         bmi.s    plr_nowaitoff
  1551.         subq.b    #1,trk_noteoffcnt(a5)
  1552.         bpl.s    plr_nowaitoff
  1553.     IFNE    SYNTH
  1554.         tst.b    trk_synthtype(a5)        ;synth/hybrid??
  1555.         beq.s    plr_nosyndec
  1556.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1557.         clr.b    trk_volwait(a5)            ;abort WAI
  1558.         bra.s    plr_nowaitoff
  1559.     ENDC
  1560. plr_nosyndec:    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1561.         bne.s    plr_nowaitoff            ;if > 0, don't stop sound
  1562.         bset    d7,d5
  1563.         move.w    d5,$dff096            ;shut DMA...
  1564.         moveq    #0,d5
  1565.     ENDC
  1566. plr_nowaitoff:
  1567.     IFNE    HOLD
  1568.         move.b    trk_fadespd(a5),d0    ;fade??
  1569.         beq.s    plr_nofade    ;no.
  1570.         sub.b    d0,trk_prevvol(a5)
  1571.         bpl.s    plr_nofade
  1572.         clr.b    trk_prevvol(a5)
  1573.         clr.b    trk_fadespd(a5)        ;fade no more
  1574.     ENDC
  1575. plr_nofade    add.b    d6,d6    ;* 2
  1576.         move.w    fx_table(pc,d6.w),d0
  1577.         jmp    fxs(pc,d0.w)
  1578. fx_table    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1579.         dc.w    fx_05-fxs,fx_06-fxs,fx_07-fxs,fx_xx-fxs,fx_xx-fxs
  1580.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_xx-fxs,fx_0d-fxs,fx_xx-fxs
  1581.         dc.w    fx_0f-fxs
  1582.         dc.w    fx_10-fxs,fx_11-fxs,fx_12-fxs,fx_13-fxs,fx_14-fxs
  1583.         dc.w    fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_18-fxs,fx_xx-fxs
  1584.         dc.w    fx_1a-fxs,fx_1b-fxs,fx_xx-fxs,fx_xx-fxs,fx_1e-fxs
  1585.         dc.w    fx_1f-fxs
  1586. fxs:
  1587. ;    **************************************** Effect 01 ******
  1588. fx_01:        tst.b    d3
  1589.         bne.s    fx_01nocnt0
  1590.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1591.         bne    fx_xx
  1592. fx_01nocnt0    sub.w    d4,trk_prevper(a5)
  1593.         move.w    trk_prevper(a5),d5
  1594.         cmp.w    #113,d5
  1595.         bge    plr_newper
  1596.         move.w    #113,d5
  1597.         move.w    d5,trk_prevper(a5)
  1598.         bra    plr_newper
  1599. ;    **************************************** Effect 11 ******
  1600. fx_11        tst.b    d3
  1601.         bne    fx_xx
  1602.         sub.w    d4,trk_prevper(a5)
  1603.         move.w    trk_prevper(a5),d5
  1604.         bra    plr_newper
  1605. ;    **************************************** Effect 02 ******
  1606. fx_02:        tst.b    d3
  1607.         bne.s    fx_02nocnt0
  1608.         btst    #5,msng_flags(a4)
  1609.         bne    fx_xx
  1610. fx_02nocnt0    add.w    d4,trk_prevper(a5)
  1611.         move.w    trk_prevper(a5),d5
  1612.         bra.w    plr_newper
  1613. ;    **************************************** Effect 12 ******
  1614. fx_12        tst.b    d3
  1615.         bne    fx_xx
  1616.         add.w    d4,trk_prevper(a5)
  1617.         move.w    trk_prevper(a5),d5
  1618.         bra    plr_newper
  1619. ;    **************************************** Effect 00 ******
  1620. fx_00:        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1621.         beq.w    fx_xx
  1622.         move.l    d3,d0
  1623.         divu    #3,d0
  1624.         swap    d0
  1625.         tst.w    d0
  1626.         bne.s    fx_arp12
  1627.         and.b    #$0f,d4
  1628.         add.b    (a5),d4
  1629.         bra.s    fx_doarp
  1630. fx_arp12:    subq.b    #1,d0
  1631.         bne.s    fx_arp2
  1632.         lsr.b    #4,d4
  1633.         add.b    (a5),d4
  1634.         bra.s    fx_doarp
  1635. fx_arp2:    move.b    (a5),d4
  1636. fx_doarp:    subq.b    #1,d4        ;-1 to make it 0 - 127
  1637.         add.b    msng_playtransp(a4),d4    ;add play transpose
  1638.         add.b    trk_stransp(a5),d4    ;add instrument transpose
  1639.         add.b    d4,d4
  1640.         movea.l    trk_periodtbl(a5),a1
  1641.         move.w    0(a1,d4.w),d5
  1642.         bra.w    plr_newtmp
  1643. ;    **************************************** Effect 04 ******
  1644. fx_14        move.b    #6,trk_vibshift(a5)
  1645.         bra.s    vib_cont
  1646. fx_04        move.b    #5,trk_vibshift(a5)
  1647. vib_cont    tst.b    d3
  1648.         bne.s    nonvib
  1649.         move.b    d4,d1
  1650.         beq.s    nonvib
  1651.         and.w    #$0f,d1
  1652.         beq.s    plr_chgvibspd
  1653.         move.w    d1,trk_vibrsz(a5)
  1654. plr_chgvibspd:    and.b    #$f0,d4
  1655.         beq.s    nonvib
  1656.         lsr.b    #3,d4
  1657.         and.b    #$3e,d4
  1658.         move.b    d4,trk_vibrspd(a5)
  1659. nonvib:        move.b    trk_vibroffs(a5),d0
  1660.         lsr.b    #2,d0
  1661.         and.w    #$1f,d0
  1662.         moveq    #0,d1
  1663.         lea    sinetable(pc),a0
  1664.         move.b    0(a0,d0.w),d5
  1665.         ext.w    d5
  1666.         muls    trk_vibrsz(a5),d5
  1667.         move.b    trk_vibshift(a5),d1
  1668.         asr.w    d1,d5
  1669.         add.w    trk_prevper(a5),d5
  1670.         move.b    trk_vibrspd(a5),d0
  1671.         add.b    d0,trk_vibroffs(a5)
  1672.         bra.w    plr_newtmp
  1673. ;    **************************************** Effect 06 ******
  1674. fx_06:        tst.b    d3
  1675.         bne.s    fx_06nocnt0
  1676.         btst    #5,msng_flags(a4)
  1677.         bne    fx_xx
  1678. fx_06nocnt0    bsr.s    plr_volslide        ;Volume slide
  1679.         bra.s    nonvib            ;+ Vibrato
  1680. ;    **************************************** Effect 07 ******
  1681. fx_07        tst.b    d3
  1682.         bne.s    nontre
  1683.         move.b    d4,d1
  1684.         beq.s    nontre
  1685.         and.w    #$0f,d1
  1686.         beq.s    plr_chgtrespd
  1687.         move.w    d1,trk_tremsz(a5)
  1688. plr_chgtrespd    and.b    #$f0,d4
  1689.         beq.s    nonvib
  1690.         lsr.b    #2,d4
  1691.         and.b    #$3e,d4
  1692.         move.b    d4,trk_tremspd(a5)
  1693. nontre        move.b    trk_tremoffs(a5),d0
  1694.         lsr.b    #3,d0
  1695.         and.w    #$1f,d0
  1696.         moveq    #0,d1
  1697.         lea    sinetable(pc),a0
  1698.         move.b    0(a0,d0.w),d5
  1699.         ext.w    d5
  1700.         muls    trk_tremsz(a5),d5
  1701.         asr.w    #7,d5
  1702.         move.b    trk_tremspd(a5),d0
  1703.         add.b    d0,trk_tremoffs(a5)
  1704.         move.b    trk_prevvol(a5),d1
  1705.         add.b    d5,d1
  1706.         bpl.s    tre_pos
  1707.         moveq    #0,d1
  1708. tre_pos        cmp.b    #64,d1
  1709.         ble.s    tre_no2hi
  1710.         moveq    #64,d1
  1711. tre_no2hi    move.b    d1,trk_tempvol(a5)
  1712.         bra.w    fx_xx
  1713. ;    **************************************** Effect 0D/0A ***
  1714. fx_0a:
  1715. fx_0d:        tst.b    d3
  1716.         bne.s    fx_0dnocnt0
  1717.         btst    #5,msng_flags(a4)
  1718.         bne    fx_xx
  1719. fx_0dnocnt0    bsr.s    plr_volslide
  1720.         bra    fx_xx
  1721. ;    ********* VOLUME SLIDE FUNCTION *************************
  1722. plr_volslide    move.b    d4,d0
  1723.         moveq    #0,d1
  1724.         move.b    trk_prevvol(a5),d1 ;move previous vol to d1
  1725.         and.b    #$f0,d0
  1726.         bne.s    crescendo
  1727.         sub.b    d4,d1    ;sub from prev. vol
  1728. voltest0    bpl.s    novolover64
  1729.         moveq    #0,d1    ;volumes under zero not accepted!!!
  1730.         bra.s    novolover64
  1731. crescendo:    lsr.b    #4,d0
  1732.         add.b    d0,d1
  1733. voltest        cmp.b    #64,d1
  1734.         ble.s    novolover64
  1735.         moveq    #64,d1
  1736. novolover64    move.b    d1,trk_prevvol(a5)
  1737.         rts
  1738. ;    **************************************** Effect 1A ******
  1739. fx_1a        tst.b    d3
  1740.         bne    fx_xx
  1741.         move.b    trk_prevvol(a5),d1
  1742.         add.b    d4,d1
  1743.         bsr.s    voltest
  1744.         bra    fx_xx
  1745. ;    **************************************** Effect 1B ******
  1746. fx_1b        tst.b    d3
  1747.         bne    fx_xx
  1748.         move.b    trk_prevvol(a5),d1
  1749.         sub.b    d4,d1
  1750.         bsr.s    voltest0
  1751.         bra    fx_xx
  1752. ;    **************************************** Effect 05 ******
  1753. fx_05:        tst.b    d3
  1754.         bne.s    fx_05nocnt0
  1755.         btst    #5,msng_flags(a4)
  1756.         bne    fx_xx
  1757. fx_05nocnt0    bsr.s    plr_volslide        ;Volume slide
  1758.         bra.s    fx_03nocnt0
  1759. ;    **************************************** Effect 03 ******
  1760. fx_03:        tst.b    d3
  1761.         bne.s    fx_03nocnt0
  1762.         btst    #5,msng_flags(a4)
  1763.         bne    fx_xx
  1764. fx_03nocnt0    move.w    trk_porttrgper(a5),d0    ;d0 = target period
  1765.         beq.w    fx_xx    ;no target period specified
  1766.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  1767.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  1768.         cmp.w    d0,d1
  1769.         bhi.s    subper    ;curr. period > target period
  1770.         add.w    d4,d1    ;add the period
  1771.         cmp.w    d0,d1
  1772.         bge.s    targreached
  1773.         bra.s    targnreach
  1774. subper:        sub.w    d4,d1    ;subtract
  1775.         cmp.w    d0,d1    ;compare current period to target period
  1776.         bgt.s    targnreach
  1777. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  1778.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  1779. targnreach:    move.w    d1,trk_prevper(a5)
  1780.         move.w    d1,d5
  1781.         bra.s    plr_newper
  1782. ;    **************************************** Effect 13 ******
  1783. fx_13:        move.w    trk_prevper(a5),d5 ;this is very simple: get the old period
  1784.         cmp.b    #3,d3        ;and..
  1785.         bge.s    plr_newper    ;if counter < 3
  1786.         sub.w    d4,d5    ;subtract effect qualifier
  1787.         bra.s    plr_newper
  1788. ;    **************************************** Effect 10 ******
  1789. fx_10:
  1790.     IFNE    MIDI
  1791.         tst.b    d3
  1792.         bne.s    fx_xx
  1793.         move.w    d4,d0
  1794.         bsr.w    _InitMIDIDump
  1795.     ENDC
  1796.         bra.s    fx_xx
  1797. ;    **************************************** Effect 1E ******
  1798. fx_1e        tst.w    blkdelay-DB(a6)
  1799.         bne.s    fx_xx
  1800.         addq.w    #1,d4
  1801.         move.w    d4,blkdelay-DB(a6)
  1802.         bra.s    fx_xx
  1803. ;    **************************************** Effect 18 ******
  1804. fx_18        cmp.b    d4,d3
  1805.         bne.s    fx_xx
  1806.         clr.b    trk_prevvol(a5)
  1807.         bra.s    fx_xx
  1808. ;    **************************************** Effect 1F ******
  1809. fx_1f        move.b    d4,d1
  1810.         lsr.b    #4,d4        ;note delay
  1811.         beq.s    nonotedelay
  1812.         cmp.b    d4,d3        ;compare to counter
  1813.         blt.s    fx_xx        ;tick not reached
  1814.         bne.s    nonotedelay
  1815.         bsr    playfxnote    ;trigger note
  1816. nonotedelay    and.w    #$0f,d1        ;retrig?
  1817.         beq.s    fx_xx
  1818.         moveq    #0,d0
  1819.         move.b    d3,d0
  1820.         divu    d1,d0
  1821.         swap    d0        ;get modulo of counter/tick
  1822.         tst.w    d0
  1823.         bne.s    fx_xx
  1824.         bsr    playfxnote    ;retrigger
  1825.         bra.s    fx_xx
  1826. ;    **************************************** Effect 0F ******
  1827. fx_0f        bsr    cmd_F
  1828. ;    *********************************************************
  1829. plr_newper
  1830. fx_xx
  1831.     IFNE    SYNTH
  1832.         move.l    trk_synthptr(a5),d0
  1833.         beq.s    plr_nosynth
  1834.         bsr.w    synth_start
  1835.         bra.s    plr_tmpper
  1836. plr_newtmp    move.l    trk_synthptr(a5),d0
  1837.         beq.s    plr_tmpper
  1838.         bsr.w    synth_start2
  1839.         bra.s    plr_tmpper
  1840.     ENDC
  1841. plr_nosynth    move.w    trk_prevper(a5),d5
  1842.     IFEQ    SYNTH
  1843. plr_newtmp
  1844.     ENDC
  1845. plr_tmpper    movea.l    trk_audioaddr(a5),a1    ;get channel address
  1846.         move.w    d5,ac_per(a1)        ;push period
  1847.         beq.s    endl
  1848.         move.b    trk_tempvol(a5),d0
  1849.         bmi.s    plr_notmpvol
  1850.         move.b    d0,ac_vol+1(a1)
  1851.         st    trk_tempvol(a5)
  1852.         bra.s    endl
  1853. plr_notmpvol    move.b    trk_prevvol(a5),ac_vol+1(a1)    ;get volume & push it
  1854. endl:        addq.b    #1,d7    ;increment channel number
  1855.         cmp.w    numtracks-DB(a6),d7    ;all channels done???
  1856.         blt.w    plr_loop1    ;not yet!!!
  1857. plr_endfx:    ;turn on DMA
  1858.         move.w    dmaonmsk-DB(a6),d0    ;dmaonmsk contains the mask of
  1859.     IFNE    MIDI
  1860.         beq.s    sdma_nodmaon    ;the channels that must be turned on
  1861.     ENDC
  1862.     IFEQ    MIDI
  1863.         beq.s    plr_exit
  1864.     ENDC
  1865.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  1866.         moveq    #80,d1
  1867. ; The following line makes the playroutine one scanline slower. If your
  1868. ; song works well without the following instruction, you can leave it out.
  1869.     IFNE    SYNTH
  1870.         add.w    d1,d1    ;sometimes double wait time is required
  1871.     ENDC
  1872.         bsr.s    _Wait1line
  1873.         move.w    d0,$dff096    ;do that!!!
  1874.         moveq    #80,d1
  1875.         bsr.s    _Wait1line
  1876.         lea    trackdataptrs-DB(a6),a1
  1877.         bsr.s    pushnewvals
  1878.         bsr.s    pushnewvals
  1879.         bsr.s    pushnewvals
  1880.         bsr.s    pushnewvals
  1881.     IFNE    MIDI
  1882. sdma_nodmaon    lea    bytesinnotebuff-DB(a6),a0
  1883.         move.w    (a0)+,d0
  1884.         beq.s    plr_exit
  1885.         bsr.w    _AddMIDId
  1886.     ENDC
  1887. plr_exit:    movem.l    (sp)+,d2-d7/a2-a6
  1888.         moveq    #1,d0
  1889.         rts
  1890.  
  1891. _Wait1line:    move.w    d0,-(sp)    ;d1 = vsync counters to wait - 1
  1892. wl0:        move.b    $dff007,d0
  1893. wl1:        cmp.b    $dff007,d0
  1894.         beq.s    wl1
  1895.         dbf    d1,wl0
  1896.         move.w    (sp)+,d0
  1897.         rts
  1898. pushnewvals:    movea.l    (a1)+,a5
  1899.         lsr.b    #1,d0
  1900.         bcc.s    rpnewv
  1901.         move.l    trk_sampleptr(a5),d1
  1902.         beq.s    rpnewv
  1903.         movea.l    trk_audioaddr(a5),a0
  1904.         move.l    d1,ac_ptr(a0)
  1905.         move.w    trk_samplelen(a5),ac_len(a0)
  1906. rpnewv:        rts
  1907.  
  1908. cmd_F        cmp.b    #$f1,d4
  1909.         bne.s    no0ff1
  1910.         cmp.b    #3,d3
  1911.         beq.s    playfxnote
  1912.         rts
  1913. no0ff1:        cmp.b    #$f2,d4
  1914.         bne.s    no0ff2
  1915.         cmp.b    #3,d3
  1916.         beq.s    playfxnote
  1917.         rts
  1918. no0ff2:        cmp.b    #$f3,d4
  1919.         bne.s    no0ff3
  1920.         move.b    d3,d0
  1921.         and.b    #2+4,d0        ;is 2 or 4
  1922.         beq.s    cF_rts
  1923. playfxnote:    moveq    #0,d1
  1924.         move.b    (a5),d1        ;get note # of previous note
  1925.         beq.s    cF_rts
  1926.         move.b    trk_noteoffcnt(a5),d0    ;get hold counter
  1927.         bmi.s    pfxn_nohold        ;no hold, or hold over
  1928.         add.b    d3,d0            ;increase by counter val
  1929.         bra.s    pfxn_hold
  1930. pfxn_nohold    move.b    trk_inithold(a5),d0    ;get initial hold
  1931.         bne.s    pfxn_hold
  1932.         st    d0
  1933. pfxn_hold    move.b    d0,trk_noteoffcnt(a5)
  1934.         movem.l    d3/a3,-(sp)
  1935.         moveq    #0,d3
  1936.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  1937.         movea.l    trk_previnstra(a5),a3
  1938.         bsr    _PlayNote
  1939.         movem.l    (sp)+,d3/a3
  1940.         rts
  1941. no0ff3:        cmp.b    #$f8,d4        ;f8 = filter off
  1942.         beq.s    plr_filteroff
  1943.         cmp.b    #$f9,d4        ;f9 = filter on
  1944.         bne.s    cF_rts
  1945.         bclr    #1,$bfe001
  1946.         rts
  1947. plr_filteroff:    bset    #1,$bfe001
  1948. cF_rts        rts
  1949.  
  1950. _SetTempo:
  1951.     IFNE    uCIAB
  1952.         move.l    _module-DB(a6),d1
  1953.         beq.s    ST_x
  1954.         move.l    d1,a0
  1955.         movea.l    mmd_songinfo(a0),a0
  1956.         btst    #5,msng_flags2(a0)
  1957.         bne.s    ST_bpm
  1958.         cmp.w    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  1959.         bhi.s    calctempo
  1960.         subq.b    #1,d0
  1961.         add.w    d0,d0
  1962.         move.w    sttempo+2(pc,d0.w),d1
  1963.         bra.s    pushtempo
  1964. calctempo:    move.l    timerdiv-DB(a6),d1
  1965.         divu    d0,d1
  1966. pushtempo:    movea.l    craddr+4-DB(a6),a0
  1967.         move.b    d1,(a0)        ;and set the CIA timer
  1968.         lsr.w    #8,d1
  1969.         movea.l    craddr+8-DB(a6),a0
  1970.         move.b    d1,(a0)
  1971.     ENDC
  1972. ST_x        rts ;   vv-- These values are the SoundTracker tempos (approx.)
  1973. sttempo:    dc.w    $0f00
  1974.     IFNE    uCIAB
  1975.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  1976. ST_bpm        move.b    msng_flags2(a0),d1
  1977.         and.w    #$1F,d1
  1978.         addq.b    #1,d1
  1979.         mulu    d1,d0
  1980.         move.l    bpmdiv-DB(a6),d1
  1981.         divu    d0,d1
  1982.         bra.s    pushtempo
  1983.     ENDC
  1984.  
  1985.     IFNE    MIDI
  1986. midicmds
  1987.     IFNE    HOLD
  1988.         tst.b    trk_noteoffcnt(a5)
  1989.         bmi.s    midi_nowaitoff
  1990.         subq.b    #1,trk_noteoffcnt(a5)
  1991.         bpl.s    midi_nowaitoff
  1992.         move.l    a5,a1
  1993.         move.b    trk_prevmidin(a5),d1
  1994.         beq.s    midi_nowaitoff    ;no note
  1995.         lea    noteondata-DB(a6),a0
  1996.         bsr.w    choff_midi
  1997. midi_nowaitoff:
  1998.     ENDC
  1999.         add.b    d6,d6    ;* 2
  2000.         move.w    midicmd_table(pc,d6.w),d0
  2001.         jmp    midifx(pc,d0.w)
  2002. midicmd_table:    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  2003.         dc.w    mfx_05-midifx,endl-midifx,endl-midifx,endl-midifx,endl-midifx
  2004.         dc.w    mfx_0a-midifx,endl-midifx,endl-midifx,mfx_0d-midifx,mfx_0e-midifx
  2005.         dc.w    mfx_0f-midifx
  2006.         dc.w    mfx_10-midifx,endl-midifx,endl-midifx,endl-midifx
  2007.         dc.w    endl-midifx,endl-midifx,endl-midifx,mfx_17-midifx
  2008.         dc.w    endl-midifx,endl-midifx,endl-midifx,endl-midifx
  2009.         dc.w    endl-midifx,endl-midifx,endl-midifx,mfx_1f-midifx
  2010. midifx
  2011. mfx_01        lea    prevmidipbend-DB(a6),a0
  2012.         moveq    #0,d1
  2013.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  2014.         add.b    d1,d1        ;UWORD index
  2015.         tst.b    d4        ;x100??
  2016.         beq.s    resetpbend
  2017.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  2018.         lsl.w    #3,d4        ;multiply bend value by 8
  2019.         add.w    d4,d0
  2020.         cmp.w    #$3fff,d0
  2021.         bls.s    bendpitch
  2022.         move.w    #$3fff,d0
  2023. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  2024.         lsr.b    #1,d1        ;back to UBYTE
  2025.         or.b    #$e0,d1
  2026.         lea    noteondata-DB(a6),a0
  2027.         move.b    d1,(a0)        ;midi command & channel
  2028.         move.b    d0,1(a0)    ;lower value
  2029.         and.b    #$7f,1(a0)    ;clear bit 7
  2030.         lsr.w    #7,d0
  2031.         and.b    #$7f,d0        ;clr bit 7
  2032.         move.b    d0,2(a0)    ;higher 7 bits
  2033.         moveq    #3,d0
  2034.         bsr.w    _AddMIDId
  2035.         bra.w    endl
  2036.  
  2037. mfx_02        lea    prevmidipbend-DB(a6),a0
  2038.         moveq    #0,d1
  2039.         move.b    trk_prevmidich(a5),d1
  2040.         add.b    d1,d1
  2041.         tst.b    d4
  2042.         beq.s    resetpbend    ;x200??
  2043.         move.w    0(a0,d1.w),d0
  2044.         lsl.w    #3,d4
  2045.         sub.w    d4,d0
  2046.         bpl.s    bendpitch    ;not under 0
  2047.         moveq    #0,d0
  2048.         bra.s    bendpitch
  2049. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  2050.         bne.w    endl
  2051.         move.w    #$2000,d0
  2052.         bra.s    bendpitch
  2053.  
  2054. mfx_03        tst.b    d3
  2055.         bne.w    endl
  2056.         lea    prevmidipbend-DB(a6),a0
  2057.         moveq    #0,d1
  2058.         move.b    trk_prevmidich(a5),d1
  2059.         add.b    d1,d1
  2060.         move.b    d4,d0
  2061.         add.b    #128,d0
  2062.         lsl.w    #6,d0
  2063.         bra.s    bendpitch
  2064.  
  2065. mfx_0d        tst.b    d3
  2066.         bne.w    endl
  2067.         lea    noteondata+1-DB(a6),a0    ;CHANNEL AFTERTOUCH
  2068.         move.b    d4,(a0)    ;value
  2069.         bmi.w    endl
  2070.         move.b    trk_prevmidich(a5),-(a0)
  2071.         or.b    #$d0,(a0)
  2072.         moveq    #2,d0
  2073.         bsr.w    _AddMIDId
  2074.         bra.w    endl
  2075.  
  2076. mfx_0a        tst.b    d3
  2077.         bne.w    endl
  2078.         lea    noteondata+2-DB(a6),a0    ;POLYPHONIC AFTERTOUCH
  2079.         and.b    #$7f,d4
  2080.         move.b    d4,(a0)
  2081.         move.b    trk_prevmidin(a5),-(a0)
  2082.         ble.w    endl
  2083.         move.b    trk_prevmidich(a5),-(a0)
  2084.         or.b    #$A0,(a0)
  2085.         moveq    #3,d0
  2086.         bsr.w    _AddMIDId
  2087.         bra.w    endl
  2088.  
  2089. mfx_17        moveq    #$07,d0        ;07 = VOLUME
  2090.         bra.s    pushctrldata
  2091.  
  2092. mfx_04        moveq    #$01,d0        ;01 = MODULATION WHEEL
  2093.         bra.s    pushctrldata
  2094.  
  2095. mfx_0e        moveq    #$0a,d0
  2096. pushctrldata    tst.b    d3        ;do it only once in a note
  2097.         bne.w    endl        ;(when counter = 0)
  2098.         lea    noteondata+2-DB(a6),a0 ;push "control change" data,
  2099.         move.b    d4,(a0)        ;second databyte
  2100.         bmi.w    endl        ;$0 - $7F only
  2101.         move.b    d0,-(a0)    ;1st databyte
  2102.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  2103.         or.b    #$b0,(a0)    ;command (B)
  2104.         moveq    #3,d0
  2105.         bsr.w    _AddMIDId
  2106.         bra.w    endl
  2107.  
  2108. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  2109.         move.b    trk_prevmidich(a5),d6
  2110.         lea    midicontrnum-DB(a6),a0
  2111.         adda.w    d6,a0
  2112.         move.b    d4,(a0)
  2113.         bra.w    endl
  2114.  
  2115. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  2116.         bne.s    nomffa
  2117.         moveq    #$40,d0
  2118.         moveq    #$7f,d4
  2119.         bra.s    pushctrldata
  2120. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  2121.         bne.s    mfx_0f_2
  2122.         moveq    #$40,d0
  2123.         moveq    #$00,d4
  2124.         bra.s    pushctrldata
  2125. mfx_0f_2    bsr.w    cmd_F
  2126.         bra.w    endl
  2127.  
  2128. mfx_00        tst.b    d4
  2129.         beq.w    endl
  2130.         and.b    #$7f,d4
  2131.         move.b    trk_prevmidich(a5),d6
  2132.         lea    midicontrnum-DB(a6),a0
  2133.         move.b    0(a0,d6.w),d0
  2134.         bra.s    pushctrldata
  2135.  
  2136. mfx_10        tst.b    d3
  2137.         bne.w    endl
  2138.         move.w    d4,d0
  2139.         bsr.w    _InitMIDIDump
  2140.         bra.w    endl
  2141.  
  2142. mfx_1f        move.b    d4,d1
  2143.         lsr.b    #4,d4        ;note delay
  2144.         beq.s    nonotedelay_m
  2145.         cmp.b    d4,d3        ;compare to counter
  2146.         blt    endl        ;tick not reached
  2147.         bne.s    nonotedelay_m
  2148.         bsr    playfxnote    ;trigger note
  2149. nonotedelay_m    and.w    #$0f,d1        ;retrig?
  2150.         beq    endl
  2151.         moveq    #0,d0
  2152.         move.b    d3,d0
  2153.         divu    d1,d0
  2154.         swap    d0        ;get modulo of counter/tick
  2155.         tst.w    d0
  2156.         bne    endl
  2157.         bsr    playfxnote    ;retrigger
  2158.         bra    endl
  2159.  
  2160. _ResetMIDI:    movem.l    d2/a2/a6,-(sp)
  2161.         movea.l    4,a6        ;ExecBase
  2162.         jsr    -$78(a6)    ;Disable()
  2163.         lea    DB,a6
  2164. ; Clear preset memory
  2165.         lea    prevmidicpres-DB(a6),a0
  2166.         clr.l    (a0)+    ;force presets to be set again
  2167.         clr.l    (a0)+    ;(clear prev. preset numbers)
  2168.         clr.l    (a0)+
  2169.         clr.l    (a0)
  2170.         clr.b    lastcmdbyte
  2171. ; Reset pitchbenders & modulation wheels
  2172.         lea    midiresd-DB(a6),a2
  2173.         move.b    #$e0,(a2)
  2174.         move.b    #$b0,3(a2)
  2175.         moveq    #15,d2
  2176. respbendl:    movea.l    a2,a0
  2177.         moveq    #6,d0
  2178.         bsr.w    _AddMIDId
  2179.         addq.b    #1,(a2)
  2180.         addq.b    #1,3(a2)
  2181.         dbf    d2,respbendl
  2182.         lea    prevmidipbend-DB(a6),a2
  2183.         moveq    #15,d2
  2184. resprevpbends:    move.w    #$2000,(a2)+
  2185.         dbf    d2,resprevpbends
  2186. ; Clear dump variables
  2187.         clr.b    sysx-DB(a6)
  2188.         lea    dumpqueue-DB(a6),a0
  2189.         move.l    a0,dqreadptr-DB(a6)
  2190.         move.l    a0,dqwriteptr-DB(a6)
  2191.         clr.w    dqentries-DB(a6)
  2192. ; Enable & exit
  2193.         movea.l    4,a6
  2194.         jsr    -$7e(a6)    ;Enable()
  2195.         movem.l    (sp)+,d2/a2/a6
  2196.         rts
  2197.     ENDC
  2198.  
  2199. ; *************************************************************************
  2200. ; *************************************************************************
  2201. ; ***********          P U B L I C   F U N C T I O N S          ***********
  2202. ; *************************************************************************
  2203. ; *************************************************************************
  2204.  
  2205.     IFEQ    EASY
  2206.         XDEF    _InitModule,_PlayModule
  2207.         XDEF    _InitPlayer,_RemPlayer,_StopPlayer
  2208.         XDEF    _ContModule
  2209.     ENDC
  2210.  
  2211. ; *************************************************************************
  2212. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  2213. ; *************************************************************************
  2214.  
  2215. _InitModule:    movem.l    a2-a3/d2,-(sp)
  2216.         move.l    a0,d0
  2217.         beq    IM_exit            ;0 => xit
  2218.     IFNE    RELVOL
  2219.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  2220.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  2221.         ext.w    d0
  2222.         lea    msng_trkvol(a1),a1    ;a1 = trkvol
  2223.         lea    trackdataptrs,a2
  2224.         moveq    #15,d1
  2225. IM_loop0    move.b    (a1)+,d2    ;get vol...
  2226.         ext.w    d2
  2227.         move.l    (a2)+,a3    ;pointer to track data
  2228.         mulu    d0,d2        ;mastervol * trackvol
  2229.         lsr.w    #4,d2
  2230.         move.w    d2,trk_trackvol(a3)
  2231.         dbf    d1,IM_loop0
  2232.     ENDC
  2233.         lea    holdvals,a2
  2234.         movea.l    a0,a3
  2235.         move.l    mmd_expdata(a0),d0    ;expdata...
  2236.         beq.s    IM_clrhlddec        ;none here
  2237.         move.l    d0,a1
  2238.         move.l    4(a1),d0        ;exp_smp
  2239.         beq.s    IM_clrhlddec    ;again.. nothing
  2240.         move.l    d0,a0        ;InstrExt...
  2241.         move.w    8(a1),d2    ;# of entries
  2242.         beq.s    IM_clrhlddec
  2243.         subq.w    #1,d2        ;- 1 (for dbf)
  2244.         move.w    10(a1),d0    ;entry size
  2245.     IFNE    MIDI
  2246.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  2247.     ENDC
  2248. IM_loop1    cmp.w    #3,d0
  2249.         ble.s    IM_noftune
  2250.         move.b    3(a0),126(a2)    ;InstrExt.finetune -> finetune
  2251. IM_noftune
  2252.     IFNE    MIDI
  2253.         cmp.w    #2,d0
  2254.         ble.s    IM_nsmnoff
  2255.         tst.b    2(a0)        ;suppress MIDI note off?
  2256.         beq.s    IM_nsmnoff
  2257.         bset    #7,inst_midich(a3)
  2258. IM_nsmnoff    addq.l    #8,a3        ;next instr
  2259.     ENDC
  2260.         move.b    1(a0),63(a2)    ;InstrExt.decay -> decay
  2261.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  2262.         adda.w    d0,a0        ;ptr to next InstrExt
  2263.         dbf    d2,IM_loop1
  2264.         bra.s    IM_exit
  2265. IM_clrhlddec    move.w    #3*63-1,d0    ;no InstrExt => clear holdvals/decays
  2266. IM_loop2    clr.b    (a2)+
  2267.         dbf    d0,IM_loop2
  2268. IM_exit        movem.l    (sp)+,a2-a3/d2
  2269.         rts
  2270. ; *************************************************************************
  2271. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  2272. ; *************************************************************************
  2273. _InitPlayer:
  2274.     IFNE    MIDI
  2275.         bsr.w    _GetSerial
  2276.         tst.l    d0
  2277.         bne.s    IP_error
  2278.     ENDC
  2279.         bsr.w    _AudioInit
  2280.         tst.l    d0
  2281.         bne.s    IP_error
  2282.         rts
  2283. IP_error    bsr.s    _RemPlayer
  2284.         moveq    #-1,d0
  2285.         rts
  2286. ; *************************************************************************
  2287. ; RemPlayer() -- free interrupt, audio, serial port etc..
  2288. ; *************************************************************************
  2289. _RemPlayer:    move.b    _timeropen,d0
  2290.         beq.s    RP_notimer    ;timer is not ours
  2291.         bsr.s    _StopPlayer
  2292. RP_notimer:    bsr.w    _AudioRem
  2293.     IFNE    MIDI
  2294.         bsr.w    _FreeSerial
  2295.     ENDC
  2296.         rts
  2297. ; *************************************************************************
  2298. ; StopPlayer() -- stop music
  2299. ; *************************************************************************
  2300. _StopPlayer:    lea    DB,a1
  2301.         move.b    _timeropen-DB(a1),d0
  2302.         beq.s    SP_end        ;res. alloc fail.
  2303.     IFNE    uCIAB
  2304.         movea.l    craddr-DB(a1),a0
  2305.         bclr    #0,(a0)        ;stop timer
  2306.     ENDC
  2307.         move.l    _module-DB(a1),d0
  2308.         beq.s    SP_nomod
  2309.         move.l    d0,a0
  2310.         clr.w    mmd_pstate(a0)
  2311.         clr.l    _module-DB(a1)
  2312. SP_nomod
  2313.     IFNE    MIDI
  2314.         clr.b    lastcmdbyte-DB(a1)
  2315.     ENDC
  2316.         bsr.w    SoundOff
  2317. SP_end        rts
  2318.  
  2319.  
  2320. _ContModule    tst.b    _timeropen
  2321.         beq.s    SP_end
  2322.         movea.l    craddr,a1
  2323.         bclr    #0,(a1)
  2324.         move.l    a0,-(sp)
  2325.         bsr.w    SoundOff
  2326.         move.l    (sp)+,a0
  2327.         moveq    #0,d0
  2328.         bra.s    contpoint
  2329. ; *************************************************************************
  2330. ; PlayModule(a0 = module)  -- initialize & play it!!
  2331. ; *************************************************************************
  2332. _PlayModule:    st    d0
  2333. contpoint    movem.l    a0/d0,-(sp)
  2334.         bsr    _InitModule
  2335.         movem.l    (sp)+,a0/d0
  2336.         move.l    a6,-(sp)
  2337.         lea    DB,a6
  2338.         tst.b    _timeropen-DB(a6)
  2339.         beq    PM_end        ;resource allocation failure
  2340.         move.l    a0,d1
  2341.         beq    PM_end        ;module failure
  2342.     IFNE    uCIAB
  2343.         movea.l    craddr-DB(a6),a1
  2344.         bclr    #0,(a1)        ;stop timer...
  2345.     ENDC
  2346.         clr.l    _module-DB(a6)
  2347.     IFNE    MIDI
  2348.         clr.b    lastcmdbyte-DB(a6)
  2349.     ENDC
  2350.         move.w    _modnum,d1
  2351.         beq.s    PM_modfound
  2352. PM_nextmod    tst.l    mmd_expdata(a0)
  2353.         beq.s    PM_modfound
  2354.         move.l    mmd_expdata(a0),a1
  2355.         tst.l    (a1)
  2356.         beq.s    PM_modfound        ;no more modules here!
  2357.         move.l    (a1),a0
  2358.         subq.w    #1,d1
  2359.         bgt.s    PM_nextmod
  2360. PM_modfound    movea.l    mmd_songinfo(a0),a1        ;song
  2361.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  2362.         btst    #0,msng_flags(a1)
  2363.         bne.s    PM_filon
  2364.         bset    #1,$bfe001
  2365.         bra.s    PM_filset
  2366. PM_filon    bclr    #1,$bfe001
  2367. PM_filset    tst.b    d0
  2368.         beq.s    PM_noclr
  2369.         clr.l    mmd_pline(a0)
  2370.         clr.l    rptline-DB(a6)
  2371.         clr.w    blkdelay-DB(a6)
  2372. PM_noclr    move.w    mmd_pseqnum(a0),d1
  2373.         add.w    #msng_playseq,d1
  2374.         move.b    0(a1,d1.w),d1        ;get first playseq entry
  2375.         move.b    d1,mmd_pblock+1(a0)
  2376.         move.w    #-1,mmd_pstate(a0)
  2377.         move.l    a0,_module-DB(a6)
  2378.         btst    #5,msng_flags2(a1)    ;BPM?
  2379.         seq    bpmcounter-DB(a6)
  2380.     IFNE    uCIAB
  2381.         move.w    msng_deftempo(a1),d0    ;get default tempo
  2382.         movea.l    craddr-DB(a6),a1
  2383.         bsr.w    _SetTempo    ;set default tempo
  2384.         bset    #0,(a1)        ;start timer => PLAY!!
  2385.     ENDC
  2386. PM_end        move.l    (sp)+,a6
  2387.         rts
  2388. ; *************************************************************************
  2389.  
  2390. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  2391.         lea    DB,a4
  2392.         moveq    #0,d2
  2393.         movea.l    4,a6
  2394. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  2395.     IFNE    AUDDEV
  2396.         moveq    #1,d2
  2397.         moveq    #-1,d0
  2398.         jsr    -$14a(a6)    ;AllocSignal()
  2399.         tst.b    d0
  2400.         bmi.w    initerr
  2401.         move.b    d0,sigbitnum-DB(a4)
  2402. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  2403.         lea    allocport-DB(a4),a1
  2404.         move.b    d0,15(a1)    ;set mp_SigBit
  2405.         move.l    a1,-(sp)
  2406.         suba.l    a1,a1
  2407.         jsr    -$126(a6)    ;FindTask(0)
  2408.         move.l    (sp)+,a1
  2409.         move.l    d0,16(a1)    ;set mp_SigTask
  2410.         lea    reqlist-DB(a4),a0
  2411.         move.l    a0,(a0)        ;NEWLIST begins...
  2412.         addq.l    #4,(a0)
  2413.         clr.l    4(a0)
  2414.         move.l    a0,8(a0)    ;NEWLIST ends...
  2415. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  2416.         moveq    #2,d2
  2417.         lea    allocreq-DB(a4),a1
  2418.         lea    audiodevname-DB(a4),a0
  2419.         moveq    #0,d0
  2420.         moveq    #0,d1
  2421.         movea.l    4,a6
  2422.         jsr    -$1bc(a6)    ;OpenDevice()
  2423.         tst.b    d0
  2424.         bne.w    initerr
  2425.         st.b    audiodevopen-DB(a4)
  2426. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open cia resource
  2427.         moveq    #3,d2
  2428.     ENDC
  2429.     IFNE    uCIAB
  2430.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  2431.         beq.s    init_pal
  2432.         move.l    #474326,timerdiv-DB(a4) ;Assume that CIA freq is 715 909 Hz
  2433.         move.l    #3579545/2,bpmdiv-DB(a4)
  2434. init_pal    moveq    #0,d3
  2435.         lea    cianame-DB(a4),a1
  2436.         move.b    #'a',3(a1)
  2437. open_ciares    moveq    #0,d0
  2438.         jsr    -$1f2(a6)    ;OpenResource()
  2439.         move.l    d0,_ciaresource
  2440.         beq.s    try_CIAB
  2441.         moveq    #4,d2
  2442.         move.l    d0,a6
  2443.         lea    timerinterrupt-DB(a4),a1
  2444.         moveq    #0,d0        ;Timer A
  2445.         jsr    -$6(a6)        ;AddICRVector()
  2446.         tst.l    d0
  2447.         beq.s    got_timer
  2448.         addq.l    #4,d3        ;add base addr index
  2449.         lea    timerinterrupt-DB(a4),a1
  2450.         moveq    #1,d0        ;Timer B
  2451.         jsr    -$6(a6)        ;AddICRVector()
  2452.         tst.l    d0
  2453.         beq.s    got_timer
  2454. try_CIAB    lea    cianame-DB(a4),a1
  2455.         cmp.b    #'a',3(a1)
  2456.         bne.s    initerr
  2457.         addq.b    #1,3(a1)
  2458.         moveq    #8,d3        ;CIAB base addr index = 8
  2459.         bra.w    open_ciares
  2460. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  2461. got_timer    lea    craddr+8-DB(a4),a6
  2462.         move.l    cia_addr(pc,d3.w),d0
  2463.         move.l    d0,(a6)
  2464.         sub.w    #$100,d0
  2465.         move.l    d0,-(a6)
  2466.         moveq    #2,d3        ;assume timer B
  2467.         btst    #9,d0        ;timer A or B ?
  2468.         bne.s    got_timerB
  2469.         subq.b    #1,d3        ;not timer B -> subtract 1
  2470.         add.w    #$100,d0    ;calc offset to timer control reg
  2471. got_timerB    add.w    #$900,d0
  2472.         move.l    d0,-(a6)
  2473.         move.l    d0,a0            ;get Control Register
  2474.         and.b    #%10000000,(a0)        ;clear CtrlReg bits 0 - 6
  2475.         move.b    d3,_timeropen-DB(a4)    ;d3: 1 = TimerA 2 = TimerB
  2476.     ENDC
  2477.     IFNE    VBLANK
  2478.         moveq    #5,d0        ;INTB_VERTB
  2479.         lea    timerinterrupt-DB(a4),a1
  2480.         jsr    -$a8(a6)    ;AddIntServer
  2481.         st    _timeropen-DB(a4)
  2482.     ENDC
  2483.         moveq    #0,d0
  2484. initret:    movem.l    (sp)+,a4/a6/d2-d3
  2485.         rts
  2486. initerr:    move.l    d2,d0
  2487.         bra.s    initret
  2488.  
  2489. cia_addr:    dc.l    $BFE501,$BFE701,$BFD500,$BFD700
  2490.  
  2491. _AudioRem:    movem.l    a5-a6,-(sp)
  2492.         lea    DB,a5
  2493.         moveq    #0,d0
  2494.         move.b    _timeropen,d0
  2495.         beq.s    rem1
  2496. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  2497.         move.l    _ciaresource,a6
  2498.         lea    timerinterrupt-DB(a5),a1
  2499.         subq.b    #1,d0
  2500.         jsr    -$c(a6)        ;RemICRVector
  2501. rem1:
  2502.     IFNE    AUDDEV
  2503.         movea.l    4,a6
  2504.         tst.b    audiodevopen-DB(a5)
  2505.         beq.s    rem2
  2506.         move.w    #$000f,$dff096    ;stop audio DMA
  2507. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  2508.         lea    allocreq-DB(a5),a1
  2509.         jsr    -$1c2(a6)    ;CloseDevice()
  2510.         clr.b    audiodevopen-DB(a5)
  2511. rem2:        moveq    #0,d0
  2512.         move.b    sigbitnum-DB(a5),d0
  2513.         bmi.s    rem3
  2514. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  2515.         jsr    -$150(a6)    ;FreeSignal()
  2516.         st    sigbitnum-DB(a5)
  2517. rem3:
  2518.     ENDC
  2519.         movem.l    (sp)+,a5-a6
  2520.         rts
  2521.  
  2522.     IFNE    MIDI
  2523. _GetSerial:    movem.l    a5-a6,-(sp)    ;Get serial port for MIDI
  2524.         lea    DB,a5
  2525.         bsr.s    GetSer2
  2526.         tst.l    d0        ;got the port??
  2527.         beq.s    rgser        ;yes
  2528.         movea.l    4,a6        ;no..try to flush serial.device:
  2529.         jsr    -$84(a6)        ;Forbid
  2530.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  2531.         lea    serdev-DB(a5),a1    ;"serial.device"
  2532.         jsr    -$114(a6)        ;FindName
  2533.         tst.l    d0
  2534.         beq.s    serdnotf        ;no serial.device!!
  2535.         move.l    d0,a1
  2536.         jsr    -$1b6(a6)        ;RemDevice
  2537. serdnotf:    jsr    -$8a(a6)        ;and Permit
  2538.         bsr.s    GetSer2        ;now try it again...
  2539. rgser:        movem.l    (sp)+,a5-a6
  2540.         rts
  2541.  
  2542. GetSer2:    movea.l    4,a6
  2543.         moveq    #0,d0
  2544.         lea    miscresname-DB(a5),a1
  2545.         jsr    -$1f2(a6)    ;OpenResource()
  2546.         move.l    d0,miscresbase-DB(a5)
  2547.         tst.l    d0
  2548.         beq.s    gserror
  2549.         move.l    d0,a6
  2550.         lea    medname-DB(a5),a1
  2551.         moveq    #0,d0        ;serial port
  2552.         jsr    -$6(a6)        ;AllocMiscResource()
  2553.         tst.l    d0
  2554.         bne.s    gserror
  2555.         lea    medname-DB(a5),a1
  2556.         moveq    #1,d0        ;serial bits
  2557.         jsr    -$6(a6)
  2558.         tst.l    d0
  2559.         beq.s    gs2_allocok
  2560.         moveq    #0,d0
  2561.         jsr    -$c(a6)        ;bits failed -> Free serial port
  2562.         bra.s    gserror
  2563. gs2_allocok    move.w    $dff01c,d0
  2564.         btst    #0,d0
  2565.         sne    intrson-DB(a5)
  2566.         moveq    #0,d0        ;TBE
  2567.         lea    serinterrupt-DB(a5),a1
  2568.         move.l    4,a6
  2569.         jsr    -$a2(a6)    ;SetIntVector()
  2570.         move.l    d0,prevtbe-DB(a5)
  2571.         move.w    #$8001,$dff09a    ;TBE on
  2572.         move.w    #114,$dff032    ;set baud rate (SERPER)
  2573.         st    serportalloc-DB(a5)
  2574.         moveq    #0,d0
  2575.         rts
  2576. gserror:    moveq    #-1,d0
  2577.         rts
  2578.  
  2579. _FreeSerial:    movem.l    a5-a6,-(sp)
  2580.         lea    DB,a5
  2581.         tst.l    miscresbase-DB(a5)
  2582.         beq.s    retfs
  2583.         tst.b    serportalloc-DB(a5)
  2584.         beq.s    retfs
  2585. wmb_loop    move.w    $dff018,d0    ;WAIT until all data sent
  2586.         btst    #12,d0        ;test TSRE bit of SERDAT
  2587.         beq.s    wmb_loop
  2588.         move.w    #$0001,$dff09a    ;disable TBE
  2589.         movea.l    4,a6
  2590.         move.l    prevtbe-DB(a5),a1
  2591.         moveq    #0,d0
  2592.         jsr    -$a2(a6)    ;SetIntVector()
  2593. fs_noptbe    movea.l    miscresbase-DB(a5),a6
  2594.         moveq    #0,d0        ;serial port
  2595.         jsr    -$c(a6)        ;FreeMiscResource()
  2596.         moveq    #1,d0        ;serial bits
  2597.         jsr    -$c(a6)
  2598.         clr.b    serportalloc-DB(a5)
  2599.         clr.b    lastcmdbyte-DB(a5)
  2600. retfs:        movem.l    (sp)+,a5-a6
  2601.         rts
  2602.  
  2603. ; Message number in d0.
  2604. _InitMIDIDump:    tst.b    serportalloc
  2605.         beq.s    idd_rts
  2606.         movem.l    a5/a6,-(sp)    ;a1 = data pointer, d1 = length
  2607.         lea    DB,a5
  2608.         movea.l    4,a6            ;ExecBase
  2609.         jsr    -$78(a6)        ;Disable()
  2610.         cmp.w    #16,dqentries-DB(a5)    ;dump queue full?
  2611.         bge.s    idd_exit        ;exit without doing anything
  2612.         lea    dqwriteptr-DB(a5),a1
  2613.         movea.l    (a1),a0
  2614.         move.w    d0,(a0)+        ;store message number
  2615.         cmpa.l    a1,a0            ;queue end?
  2616.         bne.s    idd_noresetbuff
  2617.         lea    dumpqueue-DB(a5),a0    ;reset write pointer
  2618. idd_noresetbuff    move.l    a0,(a1)            ;and write it back.
  2619.         addq.w    #1,dqentries-DB(a5)
  2620.         tst.b    sysx-DB(a5)        ;already sending data?
  2621.         bne.s    idd_exit        ;yes. Don't initiate new send.
  2622.         clr.b    lastcmdbyte-DB(a5)
  2623.         bsr    StartNewDump
  2624.         move.w    $dff018,d0        ;SERDATR
  2625.         btst    #13,d0
  2626.         beq.s    idd_exit
  2627.         move.w    #$8001,$dff09c        ;request TBE
  2628. idd_exit    jsr    -$7e(a6)        ;Enable()
  2629.         movem.l    (sp)+,a5/a6
  2630. idd_rts        rts
  2631.  
  2632. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable..(Interrupts are enabled anyway)
  2633.         move.w    #1,$9c(a0)            ;clear intreq bit
  2634.         tst.b    sysx-buffptr(a1)        ;sysx??
  2635.         bne.s    sih_sysx
  2636.         move.b    bytesinbuff-buffptr(a1),d0    ;bytesinbuff
  2637.         beq.s    exsih                ;buffer empty
  2638.         movea.l    readbuffptr-buffptr(a1),a5    ;get buffer read pointer
  2639.         move.w    #$100,d1            ;Stop bit
  2640.         move.b    (a5)+,d1            ;get byte
  2641.         move.w    d1,$30(a0)            ;and push it to SERDAT
  2642.         cmpa.l    a1,a5                ;shall we reset ptr??
  2643.         bne.s    norrbuffptr            ;not yet..
  2644.         lea    -128(a1),a5
  2645. norrbuffptr    subq.b    #1,d0                ;one less bytes in buffer
  2646.         move.b    d0,bytesinbuff-buffptr(a1)    ;remember it
  2647.         move.l    a5,readbuffptr-buffptr(a1)    ;push new read ptr back
  2648. exsih        move.w    #$c000,$9a(a0)
  2649.         rts
  2650. sih_sysx    move.w    #$100,d1
  2651.         movea.l    sysxptr-buffptr(a1),a5    ;data pointer
  2652.         move.b    (a5)+,d1
  2653.         move.l    a5,sysxptr-buffptr(a1)
  2654.         move.w    d1,$30(a0)        ;-> SERDAT
  2655.         subq.l    #1,sysxleft-buffptr(a1)    ;sub data left length
  2656.         bne.s    exsih        ;not 0w
  2657.         lea    DB,a5
  2658.         clr.b    lastcmdbyte-DB(a5)
  2659.         bsr.s    StartNewDump
  2660.         bra.s    exsih
  2661.  
  2662. StartNewDump:    tst.w    dqentries-DB(a5)    ;queue empty?
  2663.         beq.s    snd_exit2
  2664.         movea.l    dqreadptr-DB(a5),a1    ;get read pointer
  2665.         move.w    (a1)+,d0        ;get message number (D0)
  2666.         cmpa.l    #dqwriteptr,a1        ;queue end?
  2667.         bne.s    snd_noresetbuff
  2668.         lea    dumpqueue-DB(a5),a1    ;reset write pointer
  2669. snd_noresetbuff    move.l    a1,dqreadptr-DB(a5)    ;and write it back.
  2670.         subq.w    #1,dqentries-DB(a5)
  2671. ; then attempt to search the given message (# in D0)
  2672.         move.l    _module-DB(a5),d1
  2673.         beq.s    StartNewDump
  2674.         move.l    d1,a1
  2675.         move.l    mmd_expdata(a1),d1
  2676.         beq.s    StartNewDump
  2677.         move.l    d1,a1
  2678.         move.l    52(a1),d1        ;exp_dump
  2679.         beq.s    StartNewDump
  2680.         move.l    d1,a1
  2681.         cmp.w    (a1),d0
  2682.         bge.s    StartNewDump
  2683.         addq.l    #8,a1            ;points to MMDDump ptr table
  2684.         add.w    d0,d0
  2685.         add.w    d0,d0            ;number *= 4
  2686.         adda.w    d0,a1
  2687.         movea.l    (a1),a1
  2688. ; initialize send variables (msg addr. in A0)
  2689. snd_found    move.l    (a1)+,sysxleft-DB(a5)    ;length
  2690.         move.l    (a1),sysxptr-DB(a5)    ;data pointer
  2691.         st    sysx-DB(a5)
  2692.         rts
  2693. snd_exit2    clr.b    sysx-DB(a5)        ;finish dump
  2694.         rts
  2695.  
  2696. _AddMIDIData    move.l    a6,-(sp)
  2697.         lea    DB,a6
  2698.         bsr.s    _AddMIDId
  2699.         move.l    (sp)+,a6
  2700.         rts
  2701.  
  2702. _AddMIDId    movem.l    a2-a3/a5,-(sp)
  2703.         tst.b    serportalloc-DB(a6)
  2704.         beq.s    retamd1
  2705.         movea.l    4,a5
  2706.         lea    $dff09a,a3
  2707.         move.w    #$4000,(a3)    ;Disable interrupts
  2708.         addq.b    #1,$126(a5)    ;ExecBase->IDNestCnt
  2709.         lea    buffptr-DB(a6),a2    ;end of buffer (ptr)
  2710.         move.w    -130(a3),d1    ;-130(a3) = $dff018 (SERDATR)
  2711.         btst    #13,d1
  2712.         beq.s    noTBEreq
  2713.         move.w    #$8001,2(a3)    ;request TBE [2(a3) = $dff09c]
  2714. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  2715. adddataloop    move.b    (a0)+,d1    ;get byte
  2716.         bpl.s    norscheck    ;this isn't a status byte
  2717.         cmp.b    #$ef,d1        ;ignore system messages
  2718.         bhi.s    norscheck
  2719.         cmp.b    lastcmdbyte-DB(a6),d1    ;same as previos status byte?
  2720.         beq.s    samesb            ;yes, skip
  2721.         move.b    d1,lastcmdbyte-DB(a6)    ;no, don't skip but store.
  2722. norscheck    move.b    d1,(a1)+        ;push to midi send buffer
  2723.         addq.b    #1,8(a2)
  2724. samesb        cmpa.l    a2,a1            ;end of buffer??
  2725.         bne.s    noresbuffptr        ;no.
  2726.         lea    sendbuffer-DB(a6),a1    ;reset
  2727. noresbuffptr    subq.b    #1,d0
  2728.         bne.s    adddataloop
  2729.         move.l    a1,(a2)            ;push back new buffer ptr
  2730.         subq.b    #1,$126(a5)
  2731.         bge.s    retamd1
  2732.         move.w    #$c000,(a3)    ;enable interrupts again
  2733. retamd1        movem.l    (sp)+,a2-a3/a5
  2734.         rts
  2735.     ENDC
  2736.  
  2737.         DATA    __MERGED
  2738. DB:        ;Data base pointer
  2739.     IFNE    MIDI
  2740. sendbuffer    ds.b    128
  2741. buffptr        dc.l    sendbuffer
  2742. readbuffptr    dc.l    sendbuffer
  2743. bytesinbuff    dc.b    0
  2744.         dc.b    0
  2745. sysx        dc.b    0
  2746. lastcmdbyte    dc.b    0
  2747. sysxptr        dc.l    0
  2748. sysxleft    dc.l    0
  2749. dumpqueue    ds.w    16
  2750. dqwriteptr    dc.l    dumpqueue
  2751. dqreadptr    dc.l    dumpqueue
  2752. dqentries    dc.w    0
  2753.     ENDC
  2754. miscresbase    dc.l    0
  2755. timerdiv    dc.l    470000
  2756.     IFNE    AUDDEV
  2757. audiodevopen    dc.b    0
  2758. sigbitnum    dc.b    -1
  2759.     ENDC
  2760.     IFNE    MIDI
  2761. serportalloc    dc.b    0
  2762.     ENDC
  2763.         even
  2764.     IFNE    MIDI
  2765. preschgdata    dc.w    0
  2766. noteondata    dc.l    0
  2767.     ENDC
  2768. _module        dc.l    0
  2769. dmaonmsk    dc.w    0 ;\_May not be
  2770.     IFNE    MIDI
  2771. bytesinnotebuff    dc.w    0 ;/ separated!
  2772. noteonbuff    ds.b    18*3
  2773.         even
  2774. intrson        dc.b    0,0
  2775. prevtbe        dc.l    0
  2776.     ENDC
  2777.     IFNE    uCIAB
  2778. _ciaresource    dc.l    0
  2779. craddr        dc.l    0
  2780.         dc.l    0    ;tloaddr
  2781.         dc.l    0    ;thiaddr
  2782.     ENDC
  2783. timerinterrupt    dc.w    0,0,0,0,0
  2784.         dc.l    timerintname,DB
  2785.         dc.l    _IntHandler
  2786.     IFNE    MIDI
  2787. serinterrupt    dc.w    0,0,0,0,0
  2788.         dc.l    serintname,buffptr,SerIntHandler
  2789.     ENDC
  2790.     IFNE    AUDDEV
  2791. allocport    dc.l    0,0    ;succ, pred
  2792.         dc.b    4,0    ;NT_MSGPORT
  2793.         dc.l    0    ;name
  2794.         dc.b    0,0    ;flags = PA_SIGNAL
  2795.         dc.l    0    ;task
  2796. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  2797.         dc.b    5,0
  2798. allocreq    dc.l    0,0
  2799.         dc.b    0,127    ;NT_UNKNOWN, use maximum priority (127)
  2800.         dc.l    0,allocport    ;name, replyport
  2801.         dc.w    68        ;length
  2802.         dc.l    0    ;io_Device
  2803.         dc.l    0    ;io_Unit
  2804.         dc.w    0    ;io_Command
  2805.         dc.b    0,0    ;io_Flags, io_Error
  2806.         dc.w    0    ;ioa_AllocKey
  2807.         dc.l    sttempo    ;ioa_Data
  2808.         dc.l    1    ;ioa_Length
  2809.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  2810.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  2811. audiodevname    dc.b    'audio.device',0
  2812.     ENDC
  2813.     IFNE    uCIAB
  2814. cianame        dc.b    'ciax.resource',0
  2815. _timeropen    dc.b    0
  2816.     ENDC
  2817. timerintname    dc.b    'OMEDTimerInterrupt',0
  2818.     IFNE    MIDI
  2819. serintname    dc.b    'OMEDSerialInterrupt',0
  2820. miscresname    dc.b    'misc.resource',0
  2821. serdev        dc.b    'serial.device',0
  2822. medname        dc.b    'OctaMED Pro modplayer',0
  2823.     ENDC
  2824.         even
  2825.     IFNE    MIDI
  2826. midiresd    dc.b    $e0,$00,$40,$b0,$01,$00
  2827.  
  2828. midicontrnum    ds.b    16
  2829.  
  2830. prevmidicpres    dc.l    0,0,0,0 ; 16 bytes
  2831.  
  2832. prevmidipbend    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  2833.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  2834.     ENDC
  2835. ; TRACK-data structures (see definitions at the end of this file)
  2836. t03d        ds.b    22
  2837.         dc.l    $dff0a0
  2838.         ds.b    71
  2839.         dc.b    $ff
  2840.         ds.b    22
  2841.         dc.l    $dff0b0
  2842.         ds.b    71
  2843.         dc.b    $ff
  2844.         ds.b    22
  2845.         dc.l    $dff0c0
  2846.         ds.b    71
  2847.         dc.b    $ff
  2848.         ds.b    22
  2849.         dc.l    $dff0d0
  2850.         ds.b    71
  2851.         dc.b    $ff
  2852. t415d        ds.b    4*T415SZ
  2853. t815d        ds.b    8*T415SZ    ;8 bytes * 12 tracks = 96 bytes
  2854. trackdataptrs    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  2855.         dc.l    t415d,t415d+T415SZ,t415d+2*T415SZ,t415d+3*T415SZ
  2856.         dc.l    t815d,t815d+T415SZ,t815d+2*T415SZ,t815d+3*T415SZ
  2857.         dc.l    t815d+4*T415SZ,t815d+5*T415SZ,t815d+6*T415SZ
  2858.         dc.l    t815d+7*T415SZ
  2859.  
  2860. nextblock    dc.b    0 ;\ DON'T SEPARATE
  2861. nxtnoclrln    dc.b    0 :/
  2862. numtracks    dc.w    0 ;\ DON'T SEPARATE
  2863. numlines    dc.w    0 ;/
  2864. nextblockline    dc.w    0
  2865. rptline        dc.w    0 ;\ DON'T SEPARATE
  2866. rptcounter    dc.w    0 ;/
  2867. blkdelay    dc.w    0    ;block delay (PT PatternDelay)
  2868. bpmcounter    dc.w    0
  2869. bpmdiv        dc.l    3546895/2
  2870.  
  2871. holdvals    ds.b 63
  2872. decays        ds.b 63
  2873. finetunes    ds.b 63
  2874.         even
  2875.  
  2876. ; Below are the period tables. There's one table for each finetune position.
  2877.     IFNE    SYNTH
  2878.     dc.w    3424,3232,3048,2880,2712,2560,2416,2280,2152,2032,1920,1812
  2879.     dc.w    1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,906
  2880.     ENDC
  2881. per0    dc.w    856,808,762,720,678,640,604,570,538,508,480,453
  2882.     dc.w    428,404,381,360,339,320,302,285,269,254,240,226
  2883.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2884.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2885.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2886.     dc.w    214,202,190,180,170,160,151,143,135,127,120,113
  2887.     IFNE    SYNTH
  2888.     dc.w    3400,3209,3029,2859,2699,2547,2404,2269,2142,2022,1908,1801
  2889.     dc.w    1700,1605,1515,1430,1349,1274,1202,1135,1071,1011,954,901
  2890.     ENDC
  2891. per1    dc.w    850,802,757,715,674,637,601,567,535,505,477,450
  2892.     dc.w    425,401,379,357,337,318,300,284,268,253,239,225
  2893.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2894.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2895.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2896.     dc.w    213,201,189,179,169,159,150,142,134,126,119,113
  2897.     IFNE    SYNTH
  2898.     dc.w    3376,3187,3008,2839,2680,2529,2387,2253,2127,2007,1895,1788
  2899.     dc.w    1688,1593,1504,1419,1340,1265,1194,1127,1063,1004,947,894
  2900.     ENDC
  2901. per2    dc.w    844,796,752,709,670,632,597,563,532,502,474,447
  2902.     dc.w    422,398,376,355,335,316,298,282,266,251,237,224
  2903.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2904.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2905.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2906.     dc.w    211,199,188,177,167,158,149,141,133,125,118,112
  2907.     IFNE    SYNTH
  2908.     dc.w    3352,3164,2986,2819,2660,2511,2370,2237,2112,1993,1881,1776
  2909.     dc.w    1676,1582,1493,1409,1330,1256,1185,1119,1056,997,941,888
  2910.     ENDC
  2911. per3    dc.w    838,791,746,704,665,628,592,559,528,498,470,444
  2912.     dc.w    419,395,373,352,332,314,296,280,264,249,235,222
  2913.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2914.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2915.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2916.     dc.w    209,198,187,176,166,157,148,140,132,125,118,111
  2917.     IFNE    SYNTH
  2918.     dc.w    3328,3141,2965,2799,2641,2493,2353,2221,2097,1979,1868,1763
  2919.     dc.w    1664,1571,1482,1399,1321,1247,1177,1111,1048,989,934,881
  2920.     ENDC
  2921. per4    dc.w    832,785,741,699,660,623,588,555,524,495,467,441
  2922.     dc.w    416,392,370,350,330,312,294,278,262,247,233,220
  2923.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2924.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2925.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2926.     dc.w    208,196,185,175,165,156,147,139,131,124,117,110
  2927.     IFNE    SYNTH
  2928.     dc.w    3304,3119,2944,2778,2622,2475,2336,2205,2081,1965,1854,1750
  2929.     dc.w    1652,1559,1472,1389,1311,1238,1168,1103,1041,982,927,875
  2930.     ENDC
  2931. per5    dc.w    826,779,736,694,655,619,584,551,520,491,463,437
  2932.     dc.w    413,390,368,347,328,309,292,276,260,245,232,219
  2933.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2934.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2935.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2936.     dc.w    206,195,184,174,164,155,146,138,130,123,116,109
  2937.     IFNE    SYNTH
  2938.     dc.w    3280,3096,2922,2758,2603,2457,2319,2189,2066,1950,1841,1738
  2939.     dc.w    1640,1548,1461,1379,1302,1229,1160,1095,1033,975,920,869
  2940.     ENDC
  2941. per6    dc.w    820,774,730,689,651,614,580,547,516,487,460,434
  2942.     dc.w    410,387,365,345,325,307,290,274,258,244,230,217
  2943.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2944.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2945.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2946.     dc.w    205,193,183,172,163,154,145,137,129,122,115,109
  2947.     IFNE    SYNTH
  2948.     dc.w    3256,3073,2901,2738,2584,2439,2302,2173,2051,1936,1827,1725
  2949.     dc.w    1628,1537,1450,1369,1292,1220,1151,1087,1026,968,914,862
  2950.     ENDC
  2951. per7    dc.w    814,768,725,684,646,610,575,543,513,484,457,431
  2952.     dc.w    407,384,363,342,323,305,288,272,256,242,228,216
  2953.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2954.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2955.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2956.     dc.w    204,192,181,171,161,152,144,136,128,121,114,108
  2957.     IFNE    SYNTH
  2958.     dc.w    3628,3424,3232,3051,2880,2718,2565,2421,2285,2157,2036,1922
  2959.     dc.w    1814,1712,1616,1525,1440,1359,1283,1211,1143,1079,1018,961
  2960.     ENDC
  2961. per_8    dc.w    907,856,808,762,720,678,640,604,570,538,508,480
  2962.     dc.w    453,428,404,381,360,339,320,302,285,269,254,240
  2963.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2964.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2965.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2966.     dc.w    226,214,202,190,180,170,160,151,143,135,127,120
  2967.     IFNE    SYNTH
  2968.     dc.w    3588,3387,3197,3017,2848,2688,2537,2395,2260,2133,2014,1901
  2969.     dc.w    1794,1693,1598,1509,1424,1344,1269,1197,1130,1067,1007,950
  2970.     ENDC
  2971. per_7    dc.w    900,850,802,757,715,675,636,601,567,535,505,477
  2972.     dc.w    450,425,401,379,357,337,318,300,284,268,253,238
  2973.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2974.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2975.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2976.     dc.w    225,212,200,189,179,169,159,150,142,134,126,119
  2977.     IFNE    SYNTH
  2978.     dc.w    3576,3375,3186,3007,2838,2679,2529,2387,2253,2126,2007,1894
  2979.     dc.w    1788,1688,1593,1504,1419,1339,1264,1193,1126,1063,1003,947
  2980.     ENDC
  2981. per_6    dc.w    894,844,796,752,709,670,632,597,563,532,502,474
  2982.     dc.w    447,422,398,376,355,335,316,298,282,266,251,237
  2983.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2984.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2985.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2986.     dc.w    223,211,199,188,177,167,158,149,141,133,125,118
  2987.     IFNE    SYNTH
  2988.     dc.w    3548,3349,3161,2984,2816,2658,2509,2368,2235,2110,1991,1879
  2989.     dc.w    1774,1674,1580,1492,1408,1329,1254,1184,1118,1055,996,940
  2990.     ENDC
  2991. per_5    dc.w    887,838,791,746,704,665,628,592,559,528,498,470
  2992.     dc.w    444,419,395,373,352,332,314,296,280,264,249,235
  2993.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2994.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2995.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2996.     dc.w    222,209,198,187,176,166,157,148,140,132,125,118
  2997.     IFNE    SYNTH
  2998.     dc.w    3524,3326,3140,2963,2797,2640,2492,2352,2220,2095,1978,1867
  2999.     dc.w    1762,1663,1570,1482,1399,1320,1246,1176,1110,1048,989,933
  3000.     ENDC
  3001. per_4    dc.w    881,832,785,741,699,660,623,588,555,524,494,467
  3002.     dc.w    441,416,392,370,350,330,312,294,278,262,247,233
  3003.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3004.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3005.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3006.     dc.w    220,208,196,185,175,165,156,147,139,131,123,117
  3007.     IFNE    SYNTH
  3008.     dc.w    3500,3304,3118,2943,2778,2622,2475,2336,2205,2081,1964,1854
  3009.     dc.w    1750,1652,1559,1472,1389,1311,1237,1168,1102,1041,982,927
  3010.     ENDC
  3011. per_3    dc.w    875,826,779,736,694,655,619,584,551,520,491,463
  3012.     dc.w    437,413,390,368,347,328,309,292,276,260,245,232
  3013.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3014.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3015.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3016.     dc.w    219,206,195,184,174,164,155,146,138,130,123,116
  3017.     IFNE    SYNTH
  3018.     dc.w    3472,3277,3093,2920,2756,2601,2455,2317,2187,2064,1949,1839
  3019.     dc.w    1736,1639,1547,1460,1378,1301,1228,1159,1094,1032,974,920
  3020.     ENDC
  3021. per_2    dc.w    868,820,774,730,689,651,614,580,547,516,487,460
  3022.     dc.w    434,410,387,365,345,325,307,290,274,258,244,230
  3023.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3024.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3025.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3026.     dc.w    217,205,193,183,172,163,154,145,137,129,122,115
  3027.     IFNE    SYNTH
  3028.     dc.w    3448,3254,3072,2899,2737,2583,2438,2301,2172,2050,1935,1827
  3029.     dc.w    1724,1627,1536,1450,1368,1292,1219,1151,1086,1025,968,913
  3030.     ENDC
  3031. per_1    dc.w    862,814,768,725,684,646,610,575,543,513,484,457
  3032.     dc.w    431,407,384,363,342,323,305,288,272,256,242,228
  3033.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3034.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3035.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3036.     dc.w    216,203,192,181,171,161,152,144,136,128,121,114
  3037.  
  3038. _periodtable
  3039.     dc.l    per_8,per_7,per_6,per_5,per_4,per_3,per_2,per_1,per0
  3040.     dc.l    per1,per2,per3,per4,per5,per6,per7
  3041.  
  3042. songname        dc.l    0
  3043. authorname      dc.l    0
  3044. scrolltext      dc.l    0
  3045. _modnum         dc.w    0
  3046.  
  3047. is8             dc.b    0
  3048.  
  3049. name            dc.b    "MED/OctaMED Pro",0
  3050.  
  3051.                 bss     "chip",chip
  3052. _chipzero:      dc.l    0
  3053.  
  3054. ; the track-data structure definition:
  3055. trk_prevnote    EQU    0    ;previous note number
  3056. trk_previnstr    EQU    1    ;previous instrument number
  3057. trk_prevvol    EQU    2    ;previous volume
  3058. trk_prevmidich    EQU    3    ;previous MIDI channel
  3059. trk_cmd        EQU    4    ;command (the 3rd number from right)
  3060. trk_cmdqual    EQU    5    ;command qualifier (infobyte, databyte..)
  3061. trk_prevmidin    EQU    6    ;previous MIDI note
  3062. trk_noteoffcnt    EQU    7    ;note-off counter (hold)
  3063. trk_inithold    EQU    8    ;default hold for this instrument
  3064. trk_initdecay    EQU    9    ;default decay for....
  3065. trk_stransp    EQU    10    ;instrument transpose
  3066. trk_finetune    EQU    11    ;finetune
  3067. trk_soffset    EQU    12    ;new sample offset
  3068. trk_previnstra    EQU    14    ;address of the previous instrument data
  3069. trk_trackvol    EQU    18
  3070. ;    the following data only on tracks 0 - 3
  3071. trk_prevper    EQU    20    ;previous period
  3072. trk_audioaddr    EQU    22    ;hardware audio channel base address
  3073. trk_sampleptr    EQU    26    ;pointer to sample
  3074. trk_samplelen    EQU    30    ;length (>> 1)
  3075. trk_porttrgper    EQU    32    ;portamento (cmd 3) target period
  3076. trk_vibshift    EQU    34    ;vibrato shift for ASR instruction
  3077. trk_vibrspd    EQU    35    ;vibrato speed/size (cmd 4 qualifier)
  3078. trk_vibrsz    EQU    36    ;vibrato size
  3079. trk_synthptr    EQU    38    ;pointer to synthetic/hybrid instrument
  3080. trk_arpgoffs    EQU    42    ;SYNTH: current arpeggio offset
  3081. trk_arpsoffs    EQU    44    ;SYNTH: arpeggio restart offset
  3082. trk_volxcnt    EQU    46    ;SYNTH: volume execute counter
  3083. trk_wfxcnt    EQU    47    ;SYNTH: waveform execute counter
  3084. trk_volcmd    EQU    48    ;SYNTH: volume command pointer
  3085. trk_wfcmd    EQU    50    ;SYNTH: waveform command pointer
  3086. trk_volwait    EQU    52    ;SYNTH: counter for WAI (volume list)
  3087. trk_wfwait    EQU    53    ;SYNTH: counter for WAI (waveform list)
  3088. trk_synthvibspd    EQU    54    ;SYNTH: vibrato speed
  3089. trk_wfchgspd    EQU    56    ;SYNTH: period change
  3090. trk_perchg    EQU    58    ;SYNTH: curr. period change from trk_prevper
  3091. trk_envptr    EQU    60    ;SYNTH: envelope waveform pointer
  3092. trk_synvibdep    EQU    64    ;SYNTH: vibrato depth
  3093. trk_synvibwf    EQU    66       ;SYNTH: vibrato waveform
  3094. trk_synviboffs    EQU    70    ;SYNTH: vibrato pointer
  3095. trk_initvolxspd    EQU    72    ;SYNTH: volume execute speed
  3096. trk_initwfxspd    EQU    73    ;SYNTH: waveform execute speed
  3097. trk_volchgspd    EQU    74    ;SYNTH: volume change
  3098. trk_prevnote2    EQU    75    ;SYNTH: previous note
  3099. trk_synvol    EQU    76    ;SYNTH: current volume
  3100. trk_synthtype    EQU    77    ;>0 = synth, -1 = hybrid, 0 = no synth
  3101. trk_periodtbl    EQU    78    ;pointer to period table
  3102. trk_prevportspd    EQU    82    ;portamento (cmd 3) speed
  3103. trk_decay    EQU    84    ;decay
  3104. trk_fadespd    EQU    85    ;decay speed
  3105. trk_envrestart    EQU    86    ;SYNTH: envelope waveform restart point
  3106. trk_envcount    EQU    90    ;SYNTH: envelope counter
  3107. trk_split    EQU    91    ;0 = this channel not splitted (OctaMED V2)
  3108. trk_vibroffs    EQU    92    ;vibrato table offset \ DON'T SEPARATE
  3109. trk_tremoffs    EQU    93    ;tremolo table offset /
  3110. trk_tremsz    EQU    94    ;tremolo size
  3111. trk_tremspd    EQU    96    ;tremolo speed
  3112. trk_tempvol    EQU    97    ;temporary volume (for tremolo)
  3113.         END
  3114.